<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0059) -->
<HTML><HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 

<TITLE>Gears FAQ - Gears API - Google Code</TITLE>
<SCRIPT type="text/javascript"><!--
(function(){function a(){this.t={};this.tick=function(c){this.t[c]=(new Date).getTime()};this.tick("start")}var b=new a;window.jstiming={Timer:a,load:b};if(window.external&&window.external.pageT)window.jstiming.pt=window.external.pageT;})();

var _tocPath_ = '/html/apis/gears/_toc.ezt';
var codesite_token = '6757fbfd6dd741b68a9e762e4004d843';
var logged_in_user_email = 'qfel13@gmail.com';
//--></SCRIPT>
<LINK href="./Gears FAQ - Gears API - Google Code_files/codesite.pack.04102009.css" type="text/css" rel="stylesheet">
<SCRIPT src="./Gears FAQ - Gears API - Google Code_files/codesite_head.pack.04102009.js" type="text/javascript"></SCRIPT>
<SCRIPT type="text/javascript">CODESITE_CSITimer['load'].tick('bhs');</SCRIPT>
<LINK rel="search" type="application/opensearchdescription+xml" title="Google Code" href="http://code.google.com/osd.xml">

<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css"><![endif]-->

 </HEAD><BODY class="gc-documentation">

<DIV id="gc-container" class="labs">


<DIV id="codesiteContent">

 <DIV class="g-section g-tpl-170">

 <A name="gc-toc-anchor"></A>
 <DIV class="g-unit g-first" id="gc-toc">
 <UL class="treelist tlw-nested-only tlw-processed tlw-instance-0">
  <LI><A href="http://code.google.com/apis/gears/install.html">Install Google Gears</A></LI>
  <LI><A href="http://code.google.com/apis/gears/sample.html">Sample Applications</A></LI>
</UL>

<DIV class="line"></DIV>

<UL class="treelist tlw-nested-only tlw-processed tlw-instance-1">
  <LI>
    <H1 class="tlw-ignore">Developer's Guide</H1>
    <UL>
      <LI><A href="http://code.google.com/apis/gears/design.html">Getting Started</A></LI>
      <LI><A href="http://code.google.com/apis/gears/tutorial.html">Tutorial</A></LI>
      <LI><A href="http://code.google.com/apis/gears/architecture.html">Architecture</A></LI>
      <LI><A href="http://code.google.com/apis/gears/security.html">Security</A></LI>
      <LI><A href="http://code.google.com/apis/gears/tools.html">Resources and Tools</A></LI>
      <LI><A href="http://code.google.com/apis/gears/mobile.html">Gears on Mobile Devices</A></LI>
    </UL>
  </LI>
  <LI>
    <H1 class="tlw-ignore">API Reference</H1>
    <UL>
      <LI><A style="color:red" href="http://code.google.com/apis/gears/history.html">What's New?</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_summary.html">Summary</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_factory.html">Factory</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_blob.html">Blob</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_blobbuilder.html">BlobBuilder</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_canvas.html">Canvas</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_database.html">Database</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_desktop.html">Desktop</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_geolocation.html">Geolocation</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_httprequest.html">HttpRequest</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_timer.html">Timer</A></LI>
      <LI><A href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</A></LI>
    </UL>
  </LI>
</UL>

 </DIV>

 <A name="gc-pagecontent-anchor"></A>
 <DIV class="g-unit" id="gc-pagecontent" style="position: relative; ">
 <H1 class="page_title">Gears FAQ</H1>

    
    <H1 id="Google__Gearsfor__Web__UsersTOC">Gears for Web Users</H1>    
    <P>
      </P><DIV style="padding:0px 40px 0px 40px">
        <A href="#whySeeConnectionError">Why do I see a connection error when I try to install?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#isGearsInstalled">How do I know if Gears is installed on a computer I am using?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#installOnAnotherMozillaBrowser">How do I install Gears on another Mozilla based browser?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#runGearsOn64Bit">How do I run Gears on my 64-bit system?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#uninstall">How do I uninstall Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#anyAppOffline">Does Gears make any application work offline?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#whatIsDialog">Why do I see a dialog asking if I want to allow a website to use Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#geolocationOnMobile">Does Gears Geolocation work on my mobile device?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

      </DIV>

    <P></P>


    <H1 id="Getting__StartedTOC">Getting Started</H1>    
    <P>
      </P><DIV style="padding:0px 40px 0px 40px">
        <A href="#whatIsGears">What is Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howToContribute">How do I contribute to Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#status">What is the status of Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#automaticallyOffline">Does Gears automatically make my web application work offline?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#supportedSystems">What browsers and operating systems are supported by Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#needLicense">Do I need a license to use Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howToBuildApplication">How do I build an application with Gears?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#greatIdea">I have a great idea for Gears.  Whom should I contact?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

      </DIV>

    <P></P>

    <H1 id="Developing__With__GearsTOC">Developing With Gears</H1>
    <P>
      </P><DIV style="padding:0px 40px 0px 40px">
        <A href="#canGearsServeScripts">Can Gears LocalServer serve up scripting files like PHP or JSP?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#sqliteTool">Is there a tool to interactively manage and query Gears' SQLite database tables?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#deteDatabases">How do I delete databases that were created from the Gears API?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#prepareWorkerPoolCode">How do I make JavaScript source code available to a child WorkerPool during initialization?</A>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#separatePorts">If I have two applications on separate ports, will they have the same LocalServer and Database files?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#crossOriginWorker">What is a cross-origin worker? What is it useful for? How do I use it?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#multipleWorkersAccessingDB">Do I need to protect from multiple workers editing the database at once?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#storeURLParameters">Does LocalServer store URL parameters?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howToOfflineCrossOrigin">How do I 'offline' a cross-origin resource?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#queryLocalServer">Is there a tool to interactively manage and query Gears' LocalServer?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#workerPoolDOMAccess">Do WorkerPool workers have access to the DOM document object?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#isOnlineFunction">Is there an isOnline function in Gears to check whether the application is online? Do you plan to have one? Can you provide code for offline detection?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#automaticOffline">Does Gears automatically make my web application work offline?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howMakeOffilne">Gears lets my web application work offline, right? How do I do that?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howStoreData">Gears lets my web application store data on the user's computer, right? How do I do that?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#howRunBackground">Gears lets my web application run code in the background, right? How do I do that?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#linuxCompatible">What does Gears require to be compatible with my Linux system?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#whereAreFiles">Where are Gears files stored?</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

      </DIV>

    <P></P>

    <H1 id="Best__PracticesTOC">Best Practices</H1>
    <P>
      </P><DIV style="padding:0px 40px 0px 40px">
        <A href="#bestPracticeStartGears">Best Practices for Starting With Gears</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#offlineArchitectures">Best Practices for Offline Architectures</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#offlineDetection">Best Practices for Online/Offline Detection</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#bestGearsPerms">Best Practices for Gears Permissioning</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#detectingGears">Best Practices for Installation and Detection</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#cachingDifferentDomain">Best Practices for Using LocalServer With Web Applications Spread Across Different Hosts</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#bestPracticeDB">Best Practices for Database Performance and Reliability</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#offlineUI">Best Practices for Offline User Interfaces</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#maintainWorkers">Best Practices for Maintainable Workers</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#choosingNames">Best Practices for Choosing Names for Databases and LocalServers</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#storingData">Best Practices for Storing Data on Users' Machines</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#desktopShortcuts">Best Practices for Desktop Shortcuts</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#versionDBSchema">Best Practices for Versioning Database Schema</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#useMRS">Best Practices for LocalServer</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#syncing">Best Practices for Syncing</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="#webAppAsDesktop">Best Practices for Giving Web Applications Similar Features to Desktop Applications</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>
      </DIV>
    <P></P>

    <H1 id="Articles__And__TutorialsTOC">Articles And Tutorials</H1>
    <P>
      </P><DIV style="padding:0px 40px 0px 40px">
        <A href="http://code.google.com/intl/pl-PL/apis/gears/articles/gearsmonkey.html">GearsMonkey: Gears + Greasemonkey to take Wikipedia offline</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="http://code.google.com/intl/pl-PL/apis/gears/articles/take_app_offline.html">Taking Web Applications Offline with Gears</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

        <A href="http://code.google.com/intl/pl-PL/apis/gears/articles/performant_offline_app.html">Using Google Base and Gears for a Performant, Offline Experience</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>
        
        <A href="http://code.google.com/intl/pl-PL/apis/gears/articles/running_man.html">RunningMan: A location-aware stopwatch for Android</A>
        <BR>
        <SPAN style="line-height:4px">
          &nbsp;<BR>
        </SPAN>

      </DIV>

    <P></P>

    <HR>

    <H2 id="Google__Gearsfor__Web__Users">Gears for Web Users</H2>

    <DT id="whySeeConnectionError">Why do I see a connection error when I try to install?
    </DT>

    <DD>
      <P>
        Listed below are several possible causes for the connection error you're receiving. Please determine which of these causes may be applicable to you and follow the instructions to resolve the problem. 
      </P>
      <UL>
        <LI>
          Your firewall, anti-virus software, or proxy is preventing the program from accessing the Internet. In this case, you need to add it to your security software's exceptions list. If you're using Windows firewall, you can add this program by following these steps:  
          <OL>
            <LI>
              Click "Start" in your Windows Taskbar and choose "Control Panel" &gt;
              "Windows Firewall."
            </LI>
            <LI>
              Select the "Exceptions" tab.
            </LI>
            <LI>
              Click the "Add Program" button.
            </LI>
            <LI>
              Click "Browse" and select "My Computer" from the left side of the window.
            </LI>
            <LI>
              Select "Local Disk (C:)" and click "Open."
            </LI>
                        <LI>
              Double-click "Program Files" &gt;
              "Google" &gt;
              "Common."
            </LI>
            <LI>
              Select the folder with the highest number and open it.
            </LI>
            <LI>
              Choose the file "googleupdate.exe."
            </LI>
                        <LI>
              Open "Documents and Settings."
            </LI>
            <LI>
              Open the folder with your username.
            </LI>
            <LI>
              Open "Local Settings" &gt;
              "Application Data" &gt;
              "Google" &gt;
              "Update."
            </LI>
            <LI>
              Select the folder with the highest number and open it.
            </LI>
            <LI>
              Choose the file "googleupdate.exe."
            </LI>
                      </OL>
          <P>
            If you're using other firewall software, please visit that program's website for specific instructions to add applications to the exceptions list.
          </P>

        </LI>
        <LI>
          You may not have the latest updates for Windows XP. If you're not currently running Windows XP Service Pack 2, please try upgrading Windows.
        </LI>
        <BR>
        <LI>
          You’re on an authenticated proxy server that isn't supported. Currently, we support the Negotiate authentication scheme. This includes both Kerberos and NTLM, depending on what is available. Additionally, proxies using "integrated authentication" are supported, provided that the current user is authorized to go through that proxy. Please determine if you're on a supported proxy server.
        </LI>
        <BR>
        <LI>
          Your computer's Background Intelligent Transfer Service (BITS) isn't starting properly. If this is the case, you may want to verify that BITS is correctly configured. To ensure that BITS is enabled, please follow these steps:  <OL>
            <LI>
              Click the "Start" button in your Windows taskbar and select "Settings" &gt;
              "Control Panel" &gt;
              "Administrative Tools" &gt;
              "Services." 
            </LI>
            <LI>
              Select "Background Intelligent Transfer Service" from the list.
            </LI>
            <LI>
              Right-click “Background Intelligent Transfer Service” and choose "Properties" from the menu.
            </LI>
            <LI>
              From the "General" tab verify that the "Startup" type is set to either "Automatic" or "Manual." Make sure this setting is not "Disabled." 
            </LI>
          </OL>
          <P>
            If you continue to have difficulties with BITS, make sure you have write access to the following folder:
          </P>
          <P>
            C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Downloader\
          </P>
          <P>
            To determine if you have write access, right-click the folder and choose "Properties." If you see an empty box next to "Read-only" in the "General tab," you do have write access. If you see a checkmark or a green box, click the box until it's empty and click "OK." If you're unable to click the box, please speak with your system administrator. 
          </P>

        </LI>
      </UL>
    </DD>



    <DT id="isGearsInstalled">
      How do I know if Gears is installed on a computer I am using?
    </DT>

    <DD>
      <P>
        Occasionally you may wish to know if Gears is installed on a particular computer. For example, you may wish to know if Gears is installed on a computer at an internet cafe, prior to logging in with any sensitive information. Currently, there are two ways to accomplish this:
      </P>
      <UL>
        <LI>
          Visit the page  <A href="http://gears.google.com/" title="http://gears.google.com/">http://gears.google.com/</A>.  That page will clearly tell you whether Gears is installed or not.  
        </LI>
        <LI>
          Attempt to access the Gears settings dialog, which is available from the browser's Tools menu if Gears is installed.  </LI><LI>
            </LI><LI>
              Check the computer directly:  
            </LI>
            <UL>
              <LI>
                <B>Windows XP or Vista</B>
                <BR>
                Open <STRONG>Add or Remove Programs</STRONG> (on XP) or <STRONG>Programs and Features</STRONG> (on Vista) from the Windows Control Panel. If Gears is not listed, then Gears is not installed.<BR>
              </LI>
              <LI>
                <B>Mac OS X - Safari</B>
                <BR>
                In Safari, select Safari &gt; Google Gears Settings.... If the 'Google Gears Settings...' is not listed,  then Gears is not installed.  
              </LI>
              <LI>
                <B>Mac OS X or Linux - Firefox</B>
                <BR>
                In Firefox, select Tools &gt; Extensions (Firefox 1.x) or Tools &gt;  Add-ons (Firefox 2.0+) from the menu. If Gears is not listed,  then Gears is not installed.  
              </LI>
              <LI>
                <B>Windows Mobile</B>
                <BR>
                If your particular phone supports it, you can access the list of installed programs by selecting Remove Programs from the Settings page. If Gears is not listed, then Gears is not installed.  
              </LI>
            </UL>
          </UL>
        </DD>



        <DT id="installOnAnotherMozillaBrowser">
          How do I install Gears on another Mozilla based browser?
        </DT>

        <DD>
          <BR>
          There are 3 steps:
          <OL>
            <LI>
              Go to the install directory of Gears:<BR>
              <B>Mac OS X </B> - ~/Library/Application Support/Firefox/Profiles/&lt;<EM>yourprofile</EM>&gt;/extensions/{000a9d1c-beef-4f90-9363-039d445309b8}
              <BR>
              <B>Windows</B> - C:\Program Files\Google\Gears\Firefox  
              <BR>
              <B>Linux</B> - ./mozilla/firefox/&lt;<EM>yourprofile</EM>&gt;/extensions/{000a9d1c-beef-4f90-9363-039d445309b8}  
            </LI>
            <LI>
              Modify the <EM>install.rdf</EM> file:    
              <OL>
                <LI>
                  Do a search on any search engine for the GUID of the Mozilla variant you are using. The example below uses Flock's
                </LI>
                <LI>
                  Add this to your <EM>install.rdf</EM> file under the last &lt;/em:targetApplication&gt; (note: id is the GUID):
<PRE class="prettyprint"><SPAN class="tag">&lt;em:targetApplication&gt;</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="tag">&lt;Description&gt;</SPAN><SPAN class="pln"> &nbsp;<BR>&nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;em:id&gt;</SPAN><SPAN class="pln">{a463f10c-3994-11da-9945-000d60ca027b}</SPAN><SPAN class="tag">&lt;/em:id&gt;</SPAN><SPAN class="pln"> &nbsp;<BR>&nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;em:maxVersion&gt;</SPAN><SPAN class="pln">6.02</SPAN><SPAN class="tag">&lt;/em:maxVersion&gt;</SPAN><SPAN class="pln"> &nbsp; &nbsp; <BR>&nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;em:minVersion&gt;</SPAN><SPAN class="pln">0.2</SPAN><SPAN class="tag">&lt;/em:minVersion&gt;</SPAN><SPAN class="pln"> &nbsp; <BR>&nbsp; </SPAN><SPAN class="tag">&lt;/Description&gt;</SPAN><SPAN class="pln"> <BR></SPAN><SPAN class="tag">&lt;/em:targetApplication&gt;</SPAN></PRE>

                </LI>
              </OL>
              </LI><LI>
                Zip up the contents of the directory, rename the .ZIP to .XPI, drag the .XPI into your Mozilla variant.
              </LI>
            
          </OL>
        </DD>



        <DT id="runGearsOn64Bit">
          How do I run Gears on my 64-bit system?
        </DT>

        <DD>
          <P>
            There are two ways to do so.
            </P><OL>
              <LI>
                <A href="http://groups.google.com/group/gears-users/browse_thread/thread/4584842dd14a4882" title="64 bit Linux support -      Gears |      Google Groups">A patch</A>    submitted by a user.    
              </LI>
              <LI>
                A plugin called <A href="http://plugindoc.mozdev.org/linux-amd64.html#nswrapper" title="PluginDoc: Linux (x86_64)">nspluginwrapper</A> to use 32-bit browser plugins with x86_64 browsers.    
              </LI>
            </OL>
          <P></P>
        </DD>



        <DT id="uninstall">
          How do I uninstall Gears?
        </DT>

        <DD>
          To uninstall Gears, you can follow the instructions here:<A href="http://code.google.com/apis/gears/install.html" title="http://code.google.com/apis/gears/install.html">http://code.google.com/apis/gears/install.html</A>.  Once you uninstall Gears, you will no longer have offline access to applications that require Gears.
        </DD>



        <DT id="anyAppOffline">
          Does Gears make any application work offline?
        </DT>

        <DD>
          No. Only web sites that have been specifically designed to use Gears can take advantage of its offline capabilities.
        </DD>



        <DT id="whatIsDialog">
          Why do I see a dialog asking if I want to allow a website to use Gears?
        </DT>

        <DD>
          <P>
            Since Gears allows web applications to write to your computer, Gears wants to be sure that the website has your permission to do so. You will see this dialog ever time the website tries to use Gears. If you trust the website and always want to permit it to use Gears, then check "Remember my decision for this site" and click Allow.
          </P>
          <P>
            If you visit a new site that also wants to use Gears, you will see the message and can choose to give the new site permission or not.
          </P>
        </DD>

        <DT id="geolocationOnMobile">
          Does Gears Geolocation work on my mobile device?
        </DT>

        <DD>
          <P>
            Visit the <A href="http://www.google.com/support/mobile/bin/answer.py?answer=105928">Google Mobile Help Center</A> to learn about Gears Geolocation support on mobile devices.
          </P>
        </DD>






        <HR>

        <H2 id="Getting__Started">Getting Started</H2>

        <DT id="whatIsGears">
          What is Gears?
        </DT>

        <DD>
          <P>
            Gears is an open source browser extension that lets developers create web applications that can run offline. Gears provides three key features:
          </P>
          <UL>
            <LI>
              A local server, to cache and serve application resources (HTML, JavaScript, images, etc.) without needing to contact a server
            </LI>
            <LI>
              A database, to store and access data from within the browser
            </LI>
            <LI>
              A worker thread pool, to make web applications more responsive by performing expensive operations in the background
            </LI>
          </UL>
          <P>
            Gears
           is currently an early-access developers' release. It is not yet intended for use by real users in production applications at this time.
        </P>
        <BR>
        <P>
          If you're a developer interested in using Gears with your application, visit the <A href="http://code.google.com/apis/gears/">Gears Developer Page</A>.
        </P>
        <P>
          If you wish to install Gears on your computer, visit the <A href="http://gears.google.com/">Gears Home Page</A>. Please note, however, that Gears is not yet intended for general use.
        </P>
      </DD>



      <DT id="howToContribute">
        How do I contribute to Gears?
      </DT>

      <DD>
        <P>
          Go to the <A href="http://code.google.com/p/google-gears/">Google Code Project home for Gears</A>. There is also a <A href="http://code.google.com/p/google-gears/wiki/ContributingToGears">wiki document</A> that explains how to contribute to Gears.
        </P>
      </DD>



      <DT id="status">
        What is the status of Gears?
      </DT>
      <DD>
        <P>
          Gears is currently a beta product; moreover, it is currently considered to be a developer-only release. When the developer community has had a chance to examine, critique, and improve Gears, a final version suitable for use with production applications will be made available.
        </P>
        <P>
          Gears is open source software, licensed under the New BSD license. Generally speaking, this license allows you to embed the Gears runtime or API in your software, without restriction. You should, of course, consult a lawyer about licensing issues before choosing to embed Gears in your software. There is no restriction on web applications which make use of Gears installations on users' computers.
        </P>
        <P>
          Google is working with a variety of partners to make Gears widely available, and easy for developers to use.
        </P>
        <P>
          For more information, visit the <A href="http://code.google.com/apis/gears/">Gears Developers' Site</A>.
        </P>
      </DD>



      <DT id="automaticallyOffline">
        Does Gears automatically make my web application work offline?
      </DT>

      <DD>
        <P>
          Gears extends browsers by making new APIs available to JavaScript code. Like all APIs, they must be used explicitly. To take advantage of the offline features provided by Gears, you'll need to add or change code in your web application.
        </P>
        <BR>
        <P>
          There are three core modules provided by Gears: a <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A> for storing and accessing application pages offline, a <A href="http://code.google.com/apis/gears/api_database.html">Database</A> for storing and accessing application data on the user's computer, and a <A href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</A> for performing long-running tasks (such as the code that synchronizes data between your server and users' computers). For more information, follow the links.
        </P>
        <BR>
        <P>
          A <A href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</A> is available that illustrates the basic concepts. You may also find the <A href="http://code.google.com/apis/gears/sample.html">Gears sample applications</A>useful. Source code for these samples can be downloaded in a zip file found on the same page.
        </P>
      </DD>



      <DT id="supportedSystems">
        What browsers and operating systems are supported by Gears?
      </DT>

      <DD>
        <P>
          Gears works on the following browsers:
        </P>
        <UL>
          <LI>
            Apple Mac OS X (10.4 or higher, G4, G5 or Intel Processor)
          </LI>
          <UL>
            <LI>
              Firefox 1.5 or higher
            </LI>
            <LI>
              Safari 3.1.1 or higher (requires OS X Tiger 10.4.11+ or Leopard 10.5.3+, G4, G5 or Intel Processor)
            </LI>
          </UL>
          <LI>
            Linux (<A href="http://code.google.com/support/bin/answer.py?answer=71866&topic=11630">Requirements</A>)
          </LI>
          <UL>
            <LI>
              Firefox 1.5 or higher
            </LI>
          </UL>
          <LI>
            Microsoft Windows (XP or higher)
          </LI>
          <UL>
            <LI>
              Firefox 1.5 or higher
            </LI>
            <LI>
              Internet Explorer 6 or higher
            </LI>
            <LI>
              Google Chrome
            </LI>
          </UL>
          <LI>
            Microsoft Windows Mobile (5 or higher)
          </LI>
          <UL>
            <LI>
              Internet Explorer 4.01 or higher
            </LI>
            <LI>
              Opera Mobile 9.51 (Presto build 2.1.0+) (Windows Mobile 6 touchscreen devices only)
            </LI>
            <LI>
              The following devices are not supported
            </LI>
            <UL>
              <LI>
                Samsung i320 and i320N
              </LI>
              <LI>
                Orange SPV C600
              </LI>
              <LI>
                Motorola Q
              </LI>
            </UL>
          </UL>
          <LI>
            Android 1.0
          </LI>
        </UL>
      </DD>



      <DT id="needLicense">
        Do I need a license to use Gears?
      </DT>

      <DD>
        <P>
          Gears is open source software, licensed under the <A href="http://www.opensource.org/licenses/bsd-license.php">New BSD license</A>
          . Generally speaking, this license is very permissive. You should, of course, always consult an attorney if you have any questions about software licensing.
        </P>
        <P>
          There are generally two ways to use Gears: by embedding the API or runtime software in an application you distribute to end users, or by writing a web application which makes use of installations of Gears on end-users' computers.
        </P>
        <P>
          The <A href="http://www.opensource.org/licenses/bsd-license.php">New BSD license</A>
          allows you to embed the Gears runtime or API in your software, with very minimal restrictions. There are no restrictions on web applications which make use of Gears installations on users' computers.
        </P>
      </DD>



      <DT id="howToBuildApplication">
        How do I build an application with Gears?
      </DT>

      <DD>
        <P>
          Enhancing your web application with offline functionality can be challenging at first. Here are some resources to help you get started:
        </P>
        <UL>
          <LI>
            The <A href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</A>
            will walk you through the process of building a very basic, static application.
          </LI>
          <LI>
            The <A href="http://code.google.com/apis/gears/sample.html">Gears Samples</A>
            demonstrate how to use each of the core APIs included in Gears, with source code.
          </LI>
          <LI>
            Read <A href="http://code.google.com/apis/gears/architecture.html">Choosing an Offline Application Architecture</A>
            to learn about design decisions you may encounter.
          </LI>
          <LI>
            When you're ready to start debugging, check out the <A href="http://code.google.com/apis/gears/tools.html">debugging tools</A>
            .
          </LI>
        </UL>
        <P>
          If those resources don't answer your question, you can also contact other Gears developers over at the <A href="http://groups.google.com/group/gears-users">Gears Discussion Group</A>
          .
        </P>
      </DD>



      <DT id="greatIdea">
        I have a great idea for Gears.  Whom should I contact?
      </DT>

      <DD>
        <P>
          We'd love to hear your feedback and suggestions! Gears is open source software, so you should feel free to join our community. If you have a cool new idea you'd like to discuss, you should join our <A href="http://groups.google.com/group/gears-users">Google Group</A>
          and post your comment there.
        </P>
        <P>
          The Gears discussion group is intended for all topics, so don't be shy! You can post there whether your idea is about an application you'd like to build, or an enhancement or feature you'd like to see in Gears. Perhaps most importantly, you can also post there if you're having problems using Gears in an application you're building. The Gears discussion group is an open forum. Developers help each other, but the group also includes Google employees working on Gears who post regularly.
        </P>
        <P>
          If you're interested in obtaining the source code for Gears and making some enhancements of your own, you should also visit the <A href="http://code.google.com/p/google-gears/">Gears Contributors Site</A>.
        </P>
      </DD>

      <HR>

      <H2 id="Developing__With__Gears">Developing  With  Gears</H2>


      <DT id="canGearsServeScripts">
        Can Gears LocalServer serve up scripting files like PHP or JSP?
      </DT>

      <DD>
        <P>
          No. Gears LocalServer is simply a static content cache that intercepts URL requests to static content and serves them locally. The LocalServer does not provide the capability to interpret any server-side scripting.
        </P>
      </DD>



      <DT id="sqliteTool">
        Is there a tool to interactively manage and query Gears' SQLite database tables?
      </DT>

      <DD>
        <P>
          Yes. The Database Query Tool allows developers to interface with SQLite interactively via SQL commands. It can be downloaded at <A href="http://code.google.com/apis/gears/tools.html">http://code.google.com/apis/gears/tools.html</A>. Simply copy the "dbquery.html" file to your server directory and visit the URL in your browser, and you can start issuing SQL commands to the embedded SQLite. There is also a similar third party tool, called <A href="http://code.google.com/p/gearsinmotion/">Gears In Motion</A> which is very good.
        </P>
        <P>
          If you desire to check the contents of localserver.db (the database for LocalServer) then it is suggested that you use a SQLite management client. A list of them can be found <A href="http://www.sqlite.org/cvstrac/wiki?p=ManagementTools">here</A>.
        </P>
      </DD>



      <DT id="deteDatabases">
        How do I delete databases that were created from the Gears API?
      </DT>

      <DD>
        <P>
          The Gears API does not provide a programmatic way to delete an existing database. Consider the following code, which creates a Gears Database:<BR>
    </P><PRE class="prettyprint"><SPAN class="pln">db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'mydb'</SPAN><SPAN class="pun">);</SPAN></PRE>

        <P></P>
        <P>
          Databases created with code such as this can only be explicitly removed from your local machine by physically deleting the corresponding database file generated for the browser. Gears Database files reside in the Gears data directory associated with the browser. The specific path to this directory depends on your browser and the underlying operating system. The Gears data directories for common configurations are listed in <A href="http://code.google.com/apis/gears/api_database.html#directories">http://code.google.com/apis/gears/api_database.html#directories</A>.
        </P>
        <P>
          The physical database file resides below the Gears data directory, according to this format: <BR>
            </P><PRE class="prettyprint"><SPAN class="pun">[</SPAN><SPAN class="pln">path</SPAN><SPAN class="pun">]/[</SPAN><SPAN class="pln">application url</SPAN><SPAN class="pun">]/</SPAN><SPAN class="pln">http_</SPAN><SPAN class="pun">[</SPAN><SPAN class="pln">port number</SPAN><SPAN class="pun">]/[</SPAN><SPAN class="pln">db name</SPAN><SPAN class="pun">]</SPAN><SPAN class="com">#database</SPAN></PRE>
        <P></P>
      </DD>



      <DT id="prepareWorkerPoolCode">
        How do I make JavaScript source code available to a child WorkerPool during initialization?
      </DT>

      <DD>
        <P>
          Since a Gears WorkerPool worker has no access to the address space of its parent worker, all source code must be explicitly passed in during child worker initialization as such -
        </P>
          <PRE class="prettyprint"><SPAN class="pln">childCode </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'......'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> </SPAN><SPAN class="com">/* JavaScript code as string */</SPAN><SPAN class="pln"><BR>childId </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorker</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">childCode</SPAN><SPAN class="pun">);</SPAN></PRE>

        <P>
          The challenge lies in creating a string that encapsulates all the JavaScript codes that will be required by the child worker, and there are three ways to do this:<BR>
          </P><OL>
            <LI>
              You can write out the entire code as a string to be passed in. For example:<BR>
              <BR>
                <PRE class="prettyprint"><SPAN class="pln">childCode </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'function square(num) { return num*num; }'</SPAN><SPAN class="pun">;</SPAN></PRE>
            </LI>
            <LI>
              You can wrap the code into a single function and use String() to flatten the function object into a string. For example:<BR>
              <BR>
                <PRE class="prettyprint"><SPAN class="kwd">function</SPAN><SPAN class="pln"> square</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">num</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="kwd">return</SPAN><SPAN class="pln"> num </SPAN><SPAN class="pun">*</SPAN><SPAN class="pln"> num</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>childCode </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">square</SPAN><SPAN class="pun">);</SPAN></PRE>
            </LI>
            <LI>
              You can retrieve it as a file string through an AJAX invocation (since local file reading is not allowed in JavaScript). For example:<BR>
              <BR>
                <PRE class="prettyprint"><SPAN class="com">/* XMLHttpRequestObject is the XHR object of your browser */</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="typ">XMLHttpRequestObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">"GET"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'square.js'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="typ">XMLHttpRequestObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onreadystatechange </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="typ">XMLHttpRequestObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">readyState </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="lit">4</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">&amp;&amp;</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">XMLHttpRequestObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">status </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="lit">200</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; childCode </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">XMLHttpRequestObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">responseText</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="pun">}</SPAN></PRE>
            </LI>
          </OL>
        <P></P>
      </DD>



      <DT id="separatePorts">
        If I have two applications on separate ports, will they have the same LocalServer and Database files?
      </DT>

      <DD>
        <P>
          No. Separate storages are made for separate domains. Gears looks at the protocol + host + port to determine domains. A different port would be a different domain.
        </P>
      </DD>



      <DT id="crossOriginWorker">
        What is a cross-origin worker? What is it useful for? How do I use it?
      </DT>

      <DD>
        <P>
          A cross-origin worker is WorkerPool worker created in a JavaScript file on a domain and has been initialized to run JavaScript code on a cross-origin server.
        </P>
        <P>
          A cross-origin worker is useful because it is a secure solution to the cross-origin restriction policy of the browser. It allows you to make a request to a cross-origin server, even though the browser usually restricts this.
        </P>
        <P>
          What can it be used for?
        </P>
        <UL>
          <LI>
            Expose a service to users which was previously unreachable with an XMLHTTPRequest, due to cross-origin restrictions. By using cross-origin workers, you could make a web service API accessible to users' workers by putting a JavaScript worker file on your domain.
          </LI>
          <LI>
            Offline resources that are on another domain. For instance, say you have a photo site and you have a separate server for the pictures. If you wanted to enable Gears offline support, you would have to do a <EM>store.capture</EM> on them which would fail due to cross-origin restrictions. However, if you had a JavaScript file on the other origin which called <EM>store.capture</EM>, then you could initiate a worker on that file and it would be successful.
          </LI>
        </UL><BR>
        <B>Example</B>
        <P>
          Take a cross-origin resource offline with a cross-origin worker.
        </P>
        <P>

          ----<EM>cache_cross_origin_resource.html</EM>----
        </P>
              <PRE class="prettyprint"><SPAN class="tag">&lt;script</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">type</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"text/javascript"</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">src</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"gears_init.js"</SPAN><SPAN class="tag">&gt;</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="tag">&lt;/script&gt;&lt;script</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">type</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"text/javascript"</SPAN><SPAN class="tag">&gt;</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="com">// Create the workerpool</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerPool </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.workerpool'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="com">// Set the message handler for when a worker sends a message</SPAN><SPAN class="pln"><BR>workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; alert</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Received message from worker '</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sender </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">': '</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">text</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="pun">};</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="com">// Create a worker from a JavaScript file on another origin</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> childWorkerId </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorkerFromUrl</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'http://www.crossorigin.com/worker.js'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="com">// Send a message to the worker. &nbsp;The worker's onmessage handler in worker.js will decide what to do with this</SPAN><SPAN class="pln"><BR>workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'crossOriginResource.html'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> childWorkerId</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="tag">&lt;/script&gt;</SPAN></PRE>
        <P>
          ----<EM>worker.js</EM>----
        </P>
          <PRE class="prettyprint"><SPAN class="com">// Setup the WorkerPool</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> wp </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">workerPool</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="com">// Allow a cross-origin script to run this</SPAN><SPAN class="pln"><BR>wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">allowCrossOrigin</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln">b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln">messageObject</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="com">// Ignore messages from unexpected origins</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">messageObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">origin </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'http://www.expectedorigin.com'</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; </SPAN><SPAN class="com">// Create LocalServer</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> localServer </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.localserver'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> &nbsp; &nbsp;<BR>&nbsp; &nbsp; <BR>&nbsp; &nbsp; </SPAN><SPAN class="com">// Create ResourceStore (Could also use ManagedResourceStore) &nbsp; &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> store </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> localServer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Cross_Origin_Store'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> &nbsp; &nbsp;<BR>&nbsp; &nbsp; <BR>&nbsp; &nbsp; </SPAN><SPAN class="com">// We are capturing the filename sent to us by the &nbsp; &nbsp; </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; </SPAN><SPAN class="com">// WorkerPool (crossOriginResource.html) &nbsp; &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> fileToCapture </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> messageObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">text</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> &nbsp; &nbsp;<BR>&nbsp; &nbsp; <BR>&nbsp; &nbsp; </SPAN><SPAN class="com">// Capture the file &nbsp; &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; store</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">capture</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">fileToCapture</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">url</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> success</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> captureId</SPAN><SPAN class="pun">){</SPAN><SPAN class="pln"> &nbsp; &nbsp; &nbsp;<BR>&nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// When capture finishes, let the WorkerPool know the status &nbsp; &nbsp; &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// This will cause workerPool.onmessage to alert the message received &nbsp; &nbsp; &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">url </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">' captured '</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">success </SPAN><SPAN class="pun">?</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'succeeded'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'failed'</SPAN><SPAN class="pun">),</SPAN><SPAN class="pln"> messageObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sender</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> &nbsp; &nbsp;<BR>&nbsp; &nbsp; </SPAN><SPAN class="pun">});</SPAN><SPAN class="pln"><BR>&nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR></SPAN><SPAN class="pun">}</SPAN></PRE>
    </DD>



    <DT id="multipleWorkersAccessingDB">
      Do I need to protect from multiple workers editing the database at once?
    </DT>

    <DD>
      <P>
        No. SQLite is thread-safe. However, if multiple workers attempt to access the database at once then some requests might fail. It is up to the application to have workers retry requests upon failure.
      </P>
    </DD>



    <DT id="storeURLParameters">
      Does LocalServer store URL parameters?
    </DT>

    <DD>

      <P>
        Yes. If you use a ResourceStore or a ManagedResourceStore and you store a URL with parameters then whatever was captured for that URL will be served back when that URL is requested.
        Ex:
            </P><PRE class="prettyprint"><SPAN class="pln">store</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">capture</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'foobar.html?foo=1&amp;bar=2'</SPAN><SPAN class="pun">);</SPAN></PRE>
            When the browser requests <EM>foobar.html?foo=1&amp;bar=2</EM> it will be served the stored page, but not when it requests <EM>foobar.html</EM>.    
      <P></P>
    </DD>



    <DT id="howToOfflineCrossOrigin">
      How do I 'offline' a cross-origin resource?
    </DT>

    <DD>
      <P>
        First, read an article on the dangers of <A href="http://www.cgisecurity.com/articles/xss-faq.shtml">cross-origin scripting</A>.
      </P>
      <P>
        After understanding the security risks, here are two potential solutions:<BR>
        (1) Use Gears' cross-origin workers<BR>
        (2) Use cross-origin proxying  
      </P>
      <B>Solution (1)</B>
      <P>
        This is a safer alternative and therefore the suggested one. However, you must have access to put Javascript on any origins you wish to use. If you are trying to grab resources from an origin you do not control, use (2). However, be warned that this is unsafe and can expose you to attacks.
      </P>
      <P>
        Say we have two origins, http://www.foo.com/ and http://www.bar.com/ with the style.css file on bar.com. What you do is create a WorkerPool on foo.com which does a createWorkerFromUrl. The URL it will create it from is a Javascript worker file that you have placed on bar.com.
      </P>
      <P>
        The worker file on bar.com will then create a LocalServer and ResourceStore, then capture style.css.
      </P>
      <P>
        Here is example code:<BR>
      </P>
      <I>test.hml (this origin is http://www.foo.com/)</I>
          <PRE class="code">&lt;script type="text/javascript" src="gears_init.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
  var workerPool = google.gears.factory.create('beta.workerpool', '1.1');  
  workerPool.onmessage = function(a, b, message) {  
    alert('Received message from worker ' + message.sender + ': ' +  message.text);  
  };  
  var childWorkerId = workerPool.createWorkerFromUrl('http://www.bar.com/worker.js');
  workerPool.sendMessage('', childWorkerId);  
&lt;/script&gt;</PRE>
      <I>worker.js (this origin is http://www.bar.com/)</I>
          <PRE class="code">var wp = google.gears.workerPool;
wp.allowCrossOrigin();
wp.onmessage = function(a, b, message) {  
  localServer = google.gears.factory.create('beta.localserver', '1.1');    
  var store = localServer.createStore("Test_Store");    
  store.capture("style.css", function(){
    wp.sendMessage("Captured!", message.sender);
  });
}</PRE>
      For ease of reading, the try catch blocks that you should be using are left out! Don't forget them or to make sure the user has Gears installed.  
      <BR><BR>
      <B>Solution (2)</B>
      <P>
        Be sure you understand the security risks of cross-origin proxying!
      </P>
      <P>
        Use a PHP file that you store on the origin you are grabbing resources with to echo back the output of a resource from another origin. Then, to 'offline' this data, use resource store to store the PHP file with the exact parameters sent to it.
      </P>
      <P>
        An example would be if I am on http://www.foo.com/ and I have a CSS located at http://www.bar.com/style.css. I would then tell my ResourceStore to pull down the URL http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css.php_proxy.php. The php_proxy would take the input url and do an HTTP request for that resource and echo it back as an image.
      </P>
      <P>
        Here is what the code for php_proxy.php would look like:
      </P>
          <PRE class="code">&lt;?php    
header("Content-Type: text/css");
$base_url = $_GET['url'];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, false);

echo( curl_exec($ch) );
?&gt;</PRE>
          Then, in my HTML instead of:  
          <PRE class="code">&lt;link rel="stylesheet" type="text/css" media="print" href="http://www.bar.com/style.css"/&gt;</PRE>
          I would use:  
          <PRE class="code">&lt;link rel="stylesheet" type="text/css" media="print" href="http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css" /&gt;</PRE>
          The last step is to have the ResourceStore grab http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css
    </DD>

    <DT id="queryLocalServer">
      Is there a tool to interactively manage and query Gears' LocalServer?
    </DT>

    <DD>
      <STYLE type="text/css">
      /*table, table tr, table tr td { border:0; }*/#gc-pagecontent {border-left:3px solid #fff;}#breadcrumbs {padding:4px;}ul.section {list-style-type:none;line-height:155%;margin:0;padding:0 0 0 .2em}ul.section li {background-image: url(https://services.google.com/images/smallbullet.gif);background-repeat: no-repeat;background-position: 0 .6em;padding:0 0 0 .8em}.noticebox {border:1px solid #ccc;background: #efeff4;padding:6px;margin:8px 0 0 0;}</STYLE>
      <P>
        If you've been wondering how to manage the stores and resources in Gears while developing, here's a solution. A script has been written which lets you add/remove stores, and the resources inside of them.
      </P>
      <P>
        <STRONG>
          Limitations:
        </STRONG>
        </P><UL>
          <LI>
            Can only add/remove from domains the script is located on
          </LI>
          <LI>
            Must add a symlink in your profile directory
          </LI>
        </UL>
      <P></P>
      <P>
        <STRONG>
          (Mac/Linux) How to use it:
        </STRONG>
        </P><OL>
          <LI>
            Navigate to your <A href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</A>.
          </LI>
          <LI>
            Create a symlink:<BR>
                <PRE class="prettyprint"><SPAN class="pln">ln localserver</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">db </SPAN><SPAN class="str">&lt;</SPAN><EM><SPAN class="str">domain</SPAN></EM><SPAN class="str">&gt;</SPAN><SPAN class="pun">/</SPAN><SPAN class="pln">http_80</SPAN><SPAN class="pun">/</SPAN><SPAN class="pln">localserver</SPAN><SPAN class="com">#database</SPAN></PRE>
                An example would be
                <PRE class="prettyprint"><SPAN class="pln">ln localserver</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">db www</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">com</SPAN><SPAN class="pun">/</SPAN><SPAN class="pln">http_80</SPAN><SPAN class="pun">/</SPAN><SPAN class="pln">localserver</SPAN><SPAN class="com">#database</SPAN></PRE>
          </LI>
          <LI>
            Upload the <A href="http://code.google.com/articles/support/inspect_LocalServer_dbtail.html">LocalServer inspector</A> script to the domain you want to edit. Don't forget to put <A href="http://code.google.com/apis/gears/resources/gears_init.js">gears_init.js</A> there as well.    
          </LI>
          <LI>
            Navigate your browser to the location of the LocalServer inspector script.    
          </LI>
        </OL>
      <P></P>
      <P>
        </P><P>
          <STRONG>(Windows) How to use it:</STRONG>
          </P><P>
            There is no utility built in to Windows to create a hard link (the equivalent of Mac/Linux symlink). There is an <A href="http://shell-shocked.org/article.php?id=284">article</A> that talks about making hard links. A simple utility is Hard Link Magic.  
          </P>
          <P>
            Use a hard link utility to connect the <EM>localserver.db</EM> file located in your <A href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</A> to a new file, &lt;<EM>gears directory</EM>&gt;/&lt;<EM>domain</EM>&gt;/http_80/localserver#database.  
          </P>
          <P>
            Follow steps 3 &amp; 4 of the Mac/Linux section.  
          </P>

        <P></P>
        <STRONG>How it works:</STRONG>
        <P>
          The file <EM>localserver.db</EM>, located in your <A href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</A>, is an SQLite database file that keeps track of all stores and resources on all domains in your Gears LocalServer. To prevent different domains from editing each other's offline data, this file is protected from being accessed in Gears code.  
        </P>
        <P>
          By creating a symlink to that file in your domain, it is like putting the <EM>localserver.db</EM> file in that folder. The script then opens that database and queries it for the stores and databases.  
        </P>
      <P></P>
      <P>
        <STRONG>
          Troubleshooting:
        </STRONG>
        </P><P>
          If you received the "File exists" error while trying to create the symlink or there is an error when you open the LocalServer inspector tool, then delete the file &lt;<EM>GearsDirectory</EM>&gt;/&lt;<EM>domain</EM>&gt;/http_80/localserver#database and recreate the symlink.  
        </P>

      <P></P>

    </DD>



    <DT id="workerPoolDOMAccess">
      Do WorkerPool workers have access to the DOM document object?
    </DT>

    <DD>

      No, workers have no access to the DOM object. However, they can message back to their parent which can access the DOM. Also, two new modules were introduced in Gears versions 0.2+, HTTPRequest and Timer. These modules allow you to make HTTPRequests in workers, as well as use timers to execute timed events.
    </DD>



    <DT id="isOnlineFunction">
      Is there an isOnline function in Gears to check whether the application is online? Do you plan to have one? Can you provide code for offline detection?
    </DT>
    <DD>

      <P>
        No, there isn't an isOnline function in Gears at this time. And currently, there are no plans to implement it.
      </P>
      <P>
        There are 2 reasons why we haven't implemented it yet:    
        </P><OL>
          <LI>
            There are multiple definitions of the application being 'offline'. The reason could be any of these:    
            <UL>
              <LI>
                The browser has the 'work offline' flag set
              </LI>
              <LI>
                The network cable is unplugged
              </LI>
              <LI>
                The VPN is down
              </LI>
              <LI>
                DNS is down
              </LI>
              <LI>
                The server you are trying to reach is down
              </LI>
              <LI>
                The server has a bug and cannot process your request
              </LI>
            </UL>
            We can't assume how an application should determine if it is offline or not because each application will have different requirements.    
          </LI>
          <LI>
            <P>
              We don't want users to neglect syncing reliability.
            </P>
            <P>
              The popular suggestion to implement isOnline has been to make a periodic XMLHttpRequest to a resource, whose success/failure would designate the application being on/offline. The problem with this is that you cannot assume that when a ping succeeds you can start syncing and be guaranteed that that you are online. For example, if isOnline() returns true and you start sending sync updates, something could happen in the connection between the user and the server and these syncs would be permanently lost - meanwhile the application still thinks it is online.
            </P>
            <P>
              So instead what we encourage people to do is to queue all updates locally in the database module, and then try and send them to their server separately. If the update succeeds, remove them from the database. If the update fails for any reason, try again next time. In that way, you're always ready for the server to go down at any time and you never lose anything.
            </P>

          </LI>
        </OL>

      <P></P>
      <P>
        <B>
          Sample Code for periodic XMLHttpRequests
        </B>
        - uses Gears v0.2+ HTTPRequest
      </P>
      <P>
        Here is some sample code that makes use of Gears' HTTPRequest module to change the UI of an application - let the user know when they are on/offline. It requires <EM>gears_init.js</EM> to be in the same directory.  
      </P>
          <PRE class="code">&lt;div id="serverStatus"&gt;&lt;/div&gt;
&lt;div id="pings"&gt;&lt;/div&gt;
&lt;script src="gears_init.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" charset="utf-8"&gt;
  var numPings = 0;
  var request = google.gears.factory.create('beta.httprequest');
  var TIME_BETWEEN_PINGS = 3*1000;
  var PING_TIMEOUT_SECONDS = 1*1000;
  function pingSuccess() {
    if(request.responseText != "" &amp;&amp; request.responseText.indexOf("404 Page not found") == -1){
      document.getElementById('serverStatus').innerHTML = "[Server Accessible]";
    } else {    
      document.getElementById('serverStatus').innerHTML = "[Server Inaccessible]";  
    }
  }

  function isServerAvailable() {  
    var resource_to_test = "FAQs_to_write.txt";  
    resource_to_test += "?q=" + Math.floor(Math.random() * 100000);  
    request.open('GET', resource_to_test);  
    window.setTimeout("pingSuccess()",PING_TIMEOUT_SECONDS);  
    request.onreadystatechange = function() {    
      if (request.readyState == 4) {
        numPings++;
        document.getElementById('pings').innerHTML = "Number of pings: " +                                                    numPings;
      }
    };
    request.send();
    window.setTimeout("isServerAvailable()",TIME_BETWEEN_PINGS);
  }
  isServerAvailable();
&lt;/script&gt;</PRE>
      Be aware that the <EM>resource_to_test</EM> must be a file located on the same domain this code is running on. Also note that in the <EM>pingSuccess</EM> function, there is a test for a page returning "404 Page not found". Different domains will send the user a different 404 error, so please be aware of what check is correct for your domain.  
      <P>
        <B>
          Sample Code for browser being offline
        </B>

      </P>
      <P>
        To check if the user has manually told the browser to work offline, use this:
      </P>
          <PRE class="code">alert(navigator.onLine);</PRE>
      <P>
        Note: This works on IE and Firefox
      </P>
    </DD>



    <DT id="automaticOffline">
      Does Gears automatically make my web application work offline?
    </DT>

    <DD>
      <P>
        Gears extends browsers by making new APIs available to JavaScript code. Like all APIs, they must be used explicitly. To take advantage of the offline features provided by Gears, you'll need to add or change code in your web application.
      </P>
      <BR>
      <P>
        There are three core modules provided by Gears: a <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A> for storing and accessing application pages offline, a <A href="http://code.google.com/apis/gears/api_database.html">Database</A> for storing and accessing application data on the user's computer, and a <A href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</A> for performing long-running tasks (such as the code that synchronizes data between your server and users' computers). For more information, follow the links.
      </P>
      <BR>
      <P>
        A <A href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</A> is available that illustrates the basic concepts. You may also find the <A href="http://code.google.com/apis/gears/sample.html">Gears sample applications</A> useful. Source code for these samples can be downloaded in a zip file found on the same page.
      </P>
    </DD>



    <DT id="howMakeOffline">
      Gears lets my web application work offline, right? How do I do that?
    </DT>

    <DD>
      <P>
        Gears provides a LocalServer module to access application data offline. This module consists of two sub-parts:
      </P>
      <UL>
        <LI>
          A ResourceStore, used to capture application content (such as images and  static files) for later use offline  
        </LI>
        <LI>
          A ManagedResourceStore, used to capture the URLs that make up an application  
        </LI>
      </UL>
      <P>
        More information is available in the <A href="http://code.google.com/apis/gears/api_localserver.html" title="LocalServer API documentation">LocalServer API documentation</A>.
      </P>
    </DD>



    <DT id="howStoreData">
      Gears lets my web application store data on the user's computer, right? How do I do that?
    </DT>

    <DD>
      <P>
        Gears provides a Database module to store and retrieve data from a user's computer. This module consists of a SQL interface to a relational database embedded in the user's browser as part of Gears. Tables can be created to store data, in a manner that will be familiar to any SQL developer.
      </P>
      <BR>
      <P>
        More information is available in the <A href="http://code.google.com/apis/gears/api_database.html" title="Database API Documentation">Database API Documentation</A>.
      </P>
    </DD>



    <DT id="howRunBackground">
      Gears lets my web application run code in the background, right? How do I do that?
    </DT>

    <DD>
      <P>
        Gears provides a WorkerPool module to run JavaScript code in separate contexts. These contexts (which are similar to threads) run in isolated JavaScript environments, and have no window object, document object, or other DOM elements. However, these threads do have access to the XmlHttpRequest function, and so can make AJAX-style calls as necessary. This is frequently useful to implement a component that synchronizes data between a user's computer (for offline use) and the server (for online use and backup).
      </P>
      <BR>
      <P>
        Workers from the same pool can communicate with each other by passing messages.
      </P>
      <BR>
      <P>
        More information is available in the <A href="http://code.google.com/apis/gears/api_workerpool.html" title="WorkerPool API Documentation">WorkerPool API Documentation</A>.
      </P>
    </DD>



    <DT id="linuxCompatible">
      What does Gears require to be compatible with my Linux system?
    </DT>

    <DD>
      If you'd like to run the Gears for Firefox on a Linux (32-bit) platform, please make sure your system has glibc 2.3.5 or higher and libstdc++6 (Gears 0.3) or libstdc++5 (Gears pre-0.3).
    </DD>



    <DT id="whereAreFiles">
      Where are Gears files stored?
    </DT>

    <DD>
      <P>
        <STRONG>
          Windows Vista - Internet Explorer 
        </STRONG>

      </P>
      <P>
        Location: {FOLDERID_LocalAppDataLow}\Google\Gears for Internet Explorer<BR>
        Example: C:\Users\Bob\AppData\LocalLow\Google\Gears for Internet Explorer
      </P>
      <P>
        <STRONG>
          Windows Vista - Firefox 
        </STRONG>
        - Files are stored in the user local profile directory. 
      </P>
      <P>
        Location: C:\Users\&lt;username&gt;\AppData\Local\Mozilla\Firefox\Profiles\{profile}.default\Gears for Firefox <BR>
        Example: C:\Users\Bob\AppData\Local\Mozilla\Firefox\Profiles\uelib44s.default\Gears for Firefox 
      </P>
      <P>
        <STRONG>
          Windows XP - Internet Explorer 
        </STRONG>
        - Files are stored in the user local profile directory. 
      </P>
      <P>
        Location: C:\Documents and Settings\&lt;username&gt;\Local Settings\Application Data\Google\Gears for Internet Explorer<BR>
        Example: C:\Documents and Settings\Bob\Local Settings\Application Data\Google\Gears for Internet Explorer
      </P>
      <P>
        <STRONG>
          Windows XP - Firefox 
        </STRONG>
        - Files are stored in the user local profile directory. 
      </P>
      <P>
        Location: C:\Documents and Settings\&lt;username&gt;\Local Settings\Application Data\Mozilla\Firefox\Profiles\{profile}\Gears for Firefox<BR>
        Example: C:\Documents and Settings\Bob\Local Settings\Application Data\Mozilla\Firefox\Profiles\uelib44s.default\Gears for Firefox
      </P>
      <P>
        <STRONG>
          Mac OS X - Firefox 
        </STRONG>
        - Files are stored in the user local profile directory. 
      </P>
      <P>
        Location: Users/&lt;username&gt;/Library/Caches/Firefox/Profiles/{profile}.default/Gears for Firefox <BR>
        Example: Users/Bob/Library/Caches/Firefox/Profiles/08ywpi3q.default/Gears for Firefox
      </P>
      <P>
        <STRONG>
          Linux - Firefox 
        </STRONG>
        - Files are stored in the user home directory.
      </P>
      <P>
        Location: ~<EM>bob</EM>/.mozilla/firefox/&lt;firefox's profile id&gt;/Gears for Firefox <BR>
        Example: ~bob/.mozilla/firefox/08ywpi3q.default/Gears for Firefox 
      </P>
      <P>
        <STRONG>
          Microsoft Windows Mobile - Internet Explorer
        </STRONG>
        - Files are stored in the Application Data directory.
      </P>
      <P>
        Location: \Application Data\Google\Gears for Internet Explorer
      </P><BR>
      <B>What do the files do?</B>
      <P>
        <STRONG>
          localserver.db
        </STRONG>
        - This is a SQLite database that keeps track of all files that are stored in the LocalServer across all domains. This file is used in the internals of the Gears code, and cannot be accessed from within a Gears program.
      </P>
      <P>
        <STRONG>
          permissions.db
        </STRONG>
        - This is a SQLite database that keeps track of all domains that have been allowed to use Gears.
      </P>
      <P>
        <STRONG>
          &lt;<EM>domain</EM>&gt;/http_80/&lt;<EM>filename</EM>&gt;#database
        </STRONG>
        - This is a SQLite database file that has been created by an application on &lt;<EM>domain</EM>&gt;
      </P>
      <P>
        <STRONG>
          &lt;<EM>domain</EM>&gt;/http_80/&lt;<EM>filename</EM>&gt;#localserver
        </STRONG>
        - This is a folder that contains files cached by either type of LocalServer store, a ResourceStore or a ManagedResourceStore, created by &lt;<EM>domain</EM>
        &gt;
      </P>
    </DD>
        
    <HR>

    <H2 id="Best__Practices">Best Practices</H2>
    
    <DT id="bestPracticeStartGears">
      Best Practices for Starting With Gears
    </DT>
    
    <DD>
      <P>
        Most developers jump into Gears and want to take their application offline immediately. Creating offline web applications is hard. Instead, we suggest you start slowly and use other Gears features first, identifying easier projects that can get running code quickly and get you familiar with the <A href="http://code.google.com/apis/gears/">Gears API</A>. The following are some suggested ways to get your feet wet with Gears from easiest to hardest:
      </P>

      <P id="startGearsSpeedUp">
        <EM>Speed Up Static Resources</EM>
      </P>

      <P>
        The best first place to start is to use Gears to speed up your web application using the <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A> module. <A href="http://www.wordpress.com/">WordPress</A>, a popular blogging platform, <A href="http://en.blog.wordpress.com/2008/07/02/gears/">uses Gears and the LocalServer module</A> to significantly improve the performance of common operations. WordPress incorporates a rich text editor that makes authoring posts much easier. However, this editor has a ton of associated resources, such as CSS, JavaScript, images, etc. (more than a hundred!). Downloading these resources, including seeing if they have changed using traditional HTTP caching, can affect the performance of using the editor, especially on latent connections.
      </P>

      <P>
        Instead, WordPress decided to download all of these resources into a Gears LocalServer. The Gears LocalServer makes it possible to version a bundle of resources, such as JavaScript, CSS, etc. and grab them in one shot. Once files have been stored in the Gears LocalServer they are served up locally and immediately, blitting to the screen right when the page is first hit.
      </P>

      <P>
        A common question is how this is different than standard HTTP caching. Standard HTTP caching can only version individual resources, and must do validity checks on every resource at regular intervals which can affect page load time. The Gears LocalServer instead versions an entire bundle, efficiently checking that resources have changed only if the version on the bundle itself has changed. Another major difference is that Gears always serves the resources first, then revalidates the bundle. In traditional HTTP caching, you have to either choose between choosing some date far in the future to revalidate at, or revalidating before serving.
      </P>

      <P id="startGearsDataCache">
        <EM>Cache Data and Use Search Locally</EM>
      </P>

      <P>
        A great next step is to use the Gears' <A href="http://code.google.com/apis/gears/api_database.html#sqlite_fts">Full Text Search</A> capabilities to give your users very fast local search. This can be used in conjunction with the Gears <A href="http://code.google.com/apis/gears/api_database.html">Database</A> module to cache commonly used data for faster display and retrieval.
      </P>

      <P>
        <A href="http://www.myspace.com/">MySpace</A> <A href="http://gearsblog.blogspot.com/2008/05/myspace-message-center-is-now-searching.html">does this with their MySpace Mail feature</A>. They download all of a users messages in the background using a Gears <A href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</A>, index them into the Database for quick retrieval, and then drop a search form on to the page. As a user types the local database is queried in real-time, with the results shown instantaneously on the page without the latency of a round-trip server call.
      </P>

      <P>
        You can also use the local database to cache commonly used data, such as zip code lookup tables or employee contact information. For example, MySpace uses this to provide fast, client-side sorts. A user can click the sort icon while viewing messages to sort by read/unread, date sent, sender, etc. Rather than having to return to the server, affecting performance, the sort happens very fast on the client-side using SQL against the local database.
      </P>
      
      <P>
        For an example with source code you can use of caching commonly used data locally <A href="http://google-ajax-examples.googlecode.com/svn/trunk/presidentialwithgears/election2008.html">see here</A>.
      </P>

      <P id="startGearsGoingOffline">
        <EM>Going Offline</EM>
      </P>

      <P>
        Going offline can be a great step once you have familiarized yourself with Gears. See <A href="#offlineArchitectures">Best Practices for Offline Architectures</A> for details on how to begin.
      </P>
      
      <P>For more creative ways to use Gears here are some suggested uses for the various Gears modules:</P>
      
      <P id="goodUsesForLS">
        <EM>Good Uses for LocalServer</EM>
      </P>

      <UL>
        <LI>
          Caching all application resources for faster performance or offline 
          experience
        </LI>
        <LI>
          Enabling <A href="http://code.google.com/apis/gears/api_localserver.html#FileSubmitter">"offline uploads"</A>
        </LI>
        <LI>
          Caching media files
        </LI>
      </UL>  

      <P id="goodUsesForDB">
        <EM>Good Uses for Database</EM>
      </P>

      <UL>
        <LI>Caching previous internet queries</LI>
        <LI>
          Locally storing copies of remote databases for faster performance
        </LI>
      </UL>  

      <P id="goodUsesForWP">
        <EM>Good Uses for WorkerPool</EM>
      </P>

      <UL>
        <LI>Running complex computations in the background, so as not to affect UI</LI>
        <LI>Allowing <A href="#crossOriginWorker">cross-domain Ajax requests</A></LI>
        <LI>Doing all database interaction in the background</LI>
        <LI>Keeping data syncing in the background</LI>
      </UL>
    </DD>
    
    <DT id="offlineArchitectures">
      Best Practices for Offline Architectures
    </DT>
    
    <DD>
      <P>
        If you've decided that taking your web application offline is appropriate (see <A href="#bestPracticeStartGears">Best Practices for Starting With Gears</A> first), you need to decide on the architecture you will use.
      </P><P>

      </P><P>
        You must first start by deciding what to take offline. We recommend starting small. Instead of taking everything offline, identify one or two key features that your users would find particularly useful while away from the network. For example, for a blogging tool, writing posts offline is very useful, while being able to change your site's administrative settings while offline is probably not.
      </P>

      <P>
        The degree to which your web application is divided between the client and server will affect how easily you can take your application offline. In short, the more state and behavior you have on the client the easier it will be to take offline. For example, <A href="http://www.rememberthemilk.com/">Remember the Milk</A> was able to <A href="http://gearsblog.blogspot.com/2007/09/gears-case-study-what-we-learned-from.html">take their application offline in a few days</A> because it is almost entirely a thick client, Ajax application, calling exposed APIs on the server-side. An application that has almost all the logic on the server-side, however, generating 'dumb' HTML sent to the client will be much more difficult to take offline. In this case, it will be difficult in that the generation of that HTML will have to be replicated on the client when the server is unavailable.
      </P>
      
      <P>
        Next, you must decide how to do syncing. When it comes to syncing we recommend choosing your battles. The syncing problem is actually a continuum from easiest to most challenging. The easiest is to treat your local data as a read-only cache that you throw-away on each sync. The hardest is to treat offline data as both read and write that is potentially manipulated by multiple users, with automatic merging and conflict detection. The 'dumber' you can make your offline cache more towards single-user, read-only, the easier syncing will be. See <A href="#syncing">Best Practices for Syncing</A> for a more detailed discussion on this topic.
      </P>

      <P>
        Further, you need to handle how to do on- and off-line detection. See <A href="#offlineDetection">Best Practices for Online/Offline Detection</A> for more details.
      </P>

      <P>
        Finally, you need to architect your actual application. See <A href="http://code.google.com/apis/gears/architecture.html">this tutorial</A> for a full discussion on disconnected architectures. Another great resource is <A href="http://code.google.com/support/bin/answer.py?answer=73848&topic=11982">Taking Web Applications Offline with Google Gears</A> written by Omar Kilani from <A href="http://www.rememberthemilk.com/">Remember the Milk</A>.
      </P>
    </DD> 
    
    <DT id="offlineDetection">
      Best Practices for Online/Offline Detection
    </DT>
    
    <DD>
      <P>
        Online and offline detection is necessary for creating offline web applications. Two possibilities exist. Either the user manually moves into and out of offline mode through your user interface, or you automatically detect when the network appears and disappears and shift into offline mode seamlessly. We recommend starting small and doing the manual mode first. Automatic network detection is trickier than expected at first glance. While this puts a burden on the user, it can significantly simplify your code and reduce bugs. Seamless detection is a great goal to target once you have manual toggling down. Google Reader, for example, requires the user to manually click an icon to sync and download posts, and another click to move on- and off-line. Even if you have automatic network detection, you should provide a way for the user to manually attempt to go back online if they are offline. See <A href="#isOnlineFunction">this FAQ entry</A> for source code for automatic online/offline detection.
      </P>     
    </DD>
    
    <DT id="bestGearsPerms">
      Best Practices for Gears Permissioning
    </DT>
    
    <DD>
      <P>
        A bad practice is to immediately show the Gears permission dialog when a first page loads. This will annoy users. 
      </P>
      
      <P>
        Instead, we recommend having the permission dialog appear based on a user-initiated action rather than automatically. For example, in WordPress, <A href="http://en.blog.wordpress.com/2008/07/02/gears/">which uses Gears to speed up loading the blogging rich text editor</A>, a small link appears next to the editor that says "Turbo". When the user presses this link, the Gears dialog prompt appears asking the user for permission to use the <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A>. 
      </P>
      
      <P>
        The Gears permission prompt appears automatically whenever you call the <A href="http://code.google.com/apis/gears/api_factory.html">Factory APIs</A> <CODE>google.gears.factory.create</CODE> method and permission has not been granted before. Avoid calling this method during page load, and only when the user has indicated they would like to use Gears by clicking on a link or button.
      </P>

      <P>
        A related practice is to inform the user on why they should enable Gears. Rather than popping up the standard Gears dialog with no explanation on the feature, you should provide some explanatory text on what Gears will do for the user and provide an icon by using <CODE>google.gears.factory.hasPermission</CODE> and then showing the dialog using <CODE>google.gears.factory.getPermission()</CODE>:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(!</SPAN><SPAN class="pln">google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">hasPermission</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> siteName </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'My Site'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> icon </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'images/myIcon.png'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> msg </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'This site would like to use Google Gears to enable fast, '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'as-you-type searching of its documents.'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> allowed </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">getPermission</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">siteName</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> icon</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> msg</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        More information on <CODE>hasPermission</CODE> and <CODE>getPermission</CODE> are available in the <A href="http://code.google.com/apis/gears/api_factory.html">Factory API documentation</A>.
      </P>
    </DD>
    
    <DT id="detectingGears">
      Best Practices for Installation and Detection
    </DT>
    
    <DD>
      <P>
        Before using Gears, you should first detect to see if the <CODE>google.gears</CODE> object is present and available:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(!</SPAN><SPAN class="pln">window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">google </SPAN><SPAN class="pun">||</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">!</SPAN><SPAN class="pln">window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Gears not installed</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        If Gears is not present, you should display a link that when pressed will allow the user to install Gears. The Gears installation page can be customized to include your own text and message, as well as the ability to force the browser to re-navigate to your web application if the browser needed a restart:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(!</SPAN><SPAN class="pln">window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">google </SPAN><SPAN class="pun">||</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">!</SPAN><SPAN class="pln">window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> message </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'To enable fast client-side search of this website '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'please install Gears'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> url </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'http://gears.google.com/?action=install'</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'&amp;message='</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> encodeURIComponent</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">message</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'&amp;return='</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> encodeURIComponent</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">location</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">href</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; widget</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">innerHTML </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'&lt;a href="'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> url </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'"&gt;Install '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'Gears to enable fast search!&lt;/a&gt;'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">return</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">false</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN></PRE>
        
        <P>
          When using the <CODE>message</CODE> and <CODE>return</CODE> arguments on the Gears installation URL, always make sure the encode the argument values using JavaScript's <CODE>encodeURIComponent</CODE> method as in the example code above.
        </P>

        <P>
          Finally, Gears is an open source project and we highly encourage contribution. However, we must discourage hosting your own versions of Gears because the auto-updating mechanism will not work properly.  It is best for users if Gears provides a consistent user experience and can push any critical updates to all installs.
        </P>
        
        <P>
          See <A href="http://code.google.com/apis/gears/design.html#detecting">Nuts and Bolts: Detecting and Installing Gears</A> for more information.
        </P>
    </DD>
    
    <DT id="cachingDifferentDomain">
      Best Practices for Using LocalServer With Web Applications Spread Across Different Hosts
    </DT>
    
    <DD>
      <P>
        A common pattern many web sites use is to partition static content onto a separate domain, such as static.example.com, away from the main dynamic content of a web site, such as example.com. This can make working with the <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A> difficult, as the LocalServer can only download resources that come from the same domain, in this case example.com.
      </P>

      <P>
        The current way to solve this is to use <A href="#crossOriginWorker">Cross-Origin Workers</A> in conjuction with the LocalServer.
      </P>

      <P>
        First, create a file that is hosted on your static domain; in our example this would be hosted on <CODE>static.example.com</CODE> and named <CODE>cache-worker.js</CODE>. We will also have a manifest file named <CODE>manifest.js</CODE> hosted on <CODE>static.example.com</CODE> with the list of URLs to capture. The URLs in <CODE>manifest.js</CODE> will all load relative to <CODE>static.example.com</CODE>:
      </P>
      
      <P>
        ----<EM>static.example.com/manifest.js</EM>----
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="str">"betaManifestVersion"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="lit">1</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="str">"version"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"1"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="str">"entries"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">[</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"url"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"image1.png"</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">},</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"url"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"image2.png"</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">},</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"url"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"image3.png"</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">},</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"url"</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">"myCSS.css"</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">]</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
     
      <P>
        ----<EM>static.example.com/cache-worker.js</EM>----
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Setup the WorkerPool</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> wp </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">workerPool</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Allow a cross-origin script to run this</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">allowCrossOrigin</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> messageObject</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Ignore messages from unexpected origins</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">messageObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">origin </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'http://example.com'</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">&amp;&amp;</SPAN><SPAN class="pln"> messageObject</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">text </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'Download Files'</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Create LocalServer</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> localServer </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.localserver'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> &nbsp; &nbsp;<BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Create our ManagedResourceStore &nbsp; </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> store </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> localServer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">openManagedStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Cross_Origin_Store'</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">||</SPAN><SPAN class="pln"> localServer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createManagedStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Cross_Origin_Store'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; store</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">manifestUrl </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="str">'manifest.js'</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; store</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">checkForUpdate</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// if you want to get more advanced, you could setup LocalServer</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// event handlers (onprogress, oncomplete, onerror) to track status</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// of capture and send the results back as you receive them to the</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// worker that called you </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> &nbsp;<BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        We now have a cross-origin worker on <CODE>static.example.com</CODE> that we can 'message' and direct it to download its static resources into a LocalServer. Since the LocalServer is run inside of the worker on <CODE>static.example.com</CODE> it can download resources from that domain.
      </P>

      <P>
        The last piece to tie together our code is to have the primary domain, in our example <CODE>example.com</CODE>, send a message to the worker on <CODE>static.example.com</CODE> when we are ready to capture resources into the LocalServer:
      </P>
      
      <P>
        ----<EM>example.com/cache_cross_origin_resource.html</EM>----
      </P>
    
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;script</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">type</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"text/javascript"</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">src</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"gears_init.js"</SPAN><SPAN class="tag">&gt;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;/script&gt;&lt;script</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">type</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"text/javascript"</SPAN><SPAN class="tag">&gt;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Create the workerpool</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerPool </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.workerpool'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Create a worker from a JavaScript file on another origin</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> childWorkerId </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorkerFromUrl</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'http://static.example.com/cache-worker.js'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Tell worker to start downloading files into the LocalServer</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Download Files'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> childWorkerId</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;/script&gt;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>  
      
      <P>
        For more discussion on this topic see <A href="#howToOfflineCrossOrigin">How do I 'offline' a cross-origin
        resource?</A> and <A href="#crossOriginWorker">What is a cross-origin worker? What is it useful for? How do I use it?</A>.
      </P>
      
    </DD>
    
    <DT id="bestPracticeDB">
      Best Practices for Database Performance and Reliability
    </DT>
    
    <DD>
      <P>
        This section provides several tips for improving the performance and reliability when working with the Gears <A href="http://code.google.com/apis/gears/api_database.html">Database</A>.
      </P>
      
      <P>
        To increase performance:
      </P>
      
      <P>
        First, if you are doing anything more than basic reading and writing to the database, you can dramatically improve the user-experience and performance by ensuring that all reads and writes happen from a Gears <A href="http://code.google.com/apis/gears/api_workerpool.html">Worker</A>, rather than on the browser's UI thread. For example, indexing a document or data into the Gears database for full-text search is much better done on a Worker than on the browser thread, which will keep the browser responsive:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> pool </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.workerpool'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// a message handler that will be called when worker is done</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; pool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">message</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; alert</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'Finished indexing: '</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the code to run on the worker</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> indexDocument</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> messageObj</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// get arguments passed in</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> args </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> messageObj</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">body</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// open the database -- we pass in the database name when</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// messaging the worker</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">dbName</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// add a new row to our full-text search table</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">try</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'INSERT INTO ClientSearch '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'(url, title, mimeType, content) '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'VALUES (?, ?, ?, ?)'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">[</SPAN><SPAN class="pln">args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">url</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">title</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">mimeType</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">doc</SPAN><SPAN class="pun">]);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">finally</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">args</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">url</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sender</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// create worker </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerScript </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'google.gears.workerPool.onmessage = '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">indexWorker</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerID </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> pool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorker</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">workerScript</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// have worker run time-consuming database operations</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> msg </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln">url</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'somedoc.txt'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> title</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'Some Title'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mimeType</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'text/plain'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> doc</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'A short document'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dbName</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'mydatabase'</SPAN><SPAN class="pun">};</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; pool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">msg</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> workerID</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        If you were to run the above code on the main browser's thread rather than a Worker over and over your users' browsers would grind to a halt. With a Gears Worker the browser will remain responsive and usable, with overall performance faster.
      </P>
      
      <P>
        Second, if you are doing several operations at once, surrounding them with an explicit transaction will increase performance; if you don't, every call to <CODE>execute</CODE> on the Database object will have an implicit transaction, slowing things down in tight loops or when dealing with several database operations:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'my_database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'BEGIN'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">try</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// do lots of db.executes() here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'COMMIT'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">catch</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">exp</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'ROLLBACK'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">finally</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        For more information on the SQL to setup transaction see <A href="http://www.sqlite.org/lang_transaction.html">this page.</A>
      </P>
      
      <P>
        Third, the more you depend on SQL <A href="http://www.sqlite.org/lang_insert.html">INSERTs</A> rather than <A href="http://www.sqlite.org/lang_update.html">UPDATEs</A> to write data into a table the faster things will be. For example, imagine you have a network process that is slowly trickling down the information you need to add a new row to your table. You could do a single INSERT at the beginning of the process, and then run a series of UPDATEs as each new column of information comes in. However, if you simply cache this data in memory and then do one INSERT when all the data is available the Gears embedded database will perform better.
      </P>

      <P>
        To ensure reliability:
      </P>

      <P>
        First, make sure you always close <EM>both</EM> your database <EM>and</EM> your <CODE>ResultSets</CODE>. Both database connections and ResultSets are handles to OS-level resources that should be closed when finished. The best way to do this is to have a <CODE>finally</CODE> block that will get run whether an exception occurs or not:
      </P>
    
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">try</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'database-test'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'create table if not exists Test'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</SPAN><SPAN class="str">' (Phrase text, Timestamp int)'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'insert into Test values (?, ?)'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">[</SPAN><SPAN class="str">'Monkey!'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">new</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">Date</SPAN><SPAN class="pun">().</SPAN><SPAN class="pln">getTime</SPAN><SPAN class="pun">()]);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> rs </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'select * from Test order by Timestamp desc'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">while</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">isValidRow</SPAN><SPAN class="pun">())</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; alert</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">field</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">0</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'@'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">field</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">1</SPAN><SPAN class="pun">));</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="kwd">next</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">finally</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">rs</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
    
      <P>
        The second way to increase database reliability only applies if you reading or writing from the database from Workers. If you have multiple Workers or have code where both the browser and a Worker are working with the same database, you can sometimes get "Database Locked" exceptions. The best way to mitigate this is to centralize all of your database code on to a single Worker rather than have it scattered across multiple Workers or browser-code that could potentially run at the same time. A good pattern is to use a switch statement inside your worker, passing in the action to run, working with the database inside each function:
      </P>
    
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// worker.js</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> wp </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">workerPool</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; wp</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> action </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">body</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">action</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">switch</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">action</SPAN><SPAN class="pun">):</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">case</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'download'</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; download</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">break</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">case</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'index'</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; index</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">break</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">case</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'search'</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">break</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> download</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// code to download data on a worker here and store its metadata into</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the database</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> index</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// code to take a document and index it into the database here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> search</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// code to search for a document in the database here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
    
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;script</SPAN><SPAN class="pln"> </SPAN><SPAN class="atn">type</SPAN><SPAN class="pun">=</SPAN><SPAN class="atv">"text/javascript"</SPAN><SPAN class="tag">&gt;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// main.js</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerPool </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.workerpool'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> childWorkerId </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorkerFromUrl</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'worker.js'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; workerPool</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">({</SPAN><SPAN class="pln">action</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'download'</SPAN><SPAN class="pun">},</SPAN><SPAN class="pln"> childWorkerId</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="tag">&lt;/script&gt;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
       
    </DD>
    
    <DT id="offlineUI">
      Best Practices for Offline User Interfaces
    </DT>
    
    <DD>
      <P>
        Web applications that work offline should have the following elements:
      </P>
      
      <UL>
        <LI>Online/offline indicator - This can either switch automatically or be toggled manually by the user to move on- or off-line. See Best Practices for Online/Offline Detection for details.</LI>
        <LI>Sync button and feedback - A button to initiate syncing (might possibly happen automatically when the network reappears) and suitable feedback to the user during the syncing process so they know activity is occuring.</LI>
        <LI>Offline settings - A way to configure your offline application. This should include the ability to manually disable offline ability if the user does not wish to use this feature anymore. It should also include the ability to manually create a new desktop shortcut if you are using this feature (see Best Practices for Desktop Shortcuts).</LI>
        <LI>Disabled elements - Portions of your user interface that do not work offline, such as searching, should be disabled.</LI>
      </UL>
      
      <P>
        In general, your web application should allow the user to manually turn on offline ability with a small link in your application's toolbar, such as the word "Offline". Here is a screenshot from Google Docs:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline1.png">
      </P>
    
      <P>
        When pressed, you should show a permission dialog informing the user about using your application offline and asking for Gears permission; see <A href="#bestGearsPerms">Best Practices for Gears Permissioning</A> for more information on customizing the Gears permission dialog. It is important that users not try to setup an offline application on a shared, public computer, such as in an Internet cafe. See <A href="#storingData">Best Practices for Storing Data on Users' Machines</A> for more information on this. Here is the modal permission dialog that <A href="http://docs.google.com/">Google Docs</A> shows:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline2.png">
      </P>
      
      <P>
        Once setup, you should indicate to the user three modes: online, offline, and syncing. During syncing, you should provide a short message for the user informing them on syncing status. A screenshot from Google Docs:
      </P>  
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline3.png">
      </P>
      
      <P>
        When online and synced, you should display a small icon. A screenshot from Google Docs:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline4.png">
      </P>
      
      <P>
        Since users might wonder what this icon is, it is good to provide a small label that appears when the user mouses over, such as "Online. Click for Details." When clicked Google Docs shows the following:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline5.png">
      </P>
      
      <P>
        You should also show an icon when offline with a label when the mouse is run over it. Google Docs shows the following for the icon:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline6.png">
      </P>
      
      <P>
        When you run the mouse over this icon, a label appears that says "Offline. No Connection is Available." When the icon is pressed, you should provide the user with some context and a way to manually try to reconnect:
      </P>
        
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline7.png">
      </P>
      
      <P>
        The decision on whether to make online and offline detection manual or automatic is up to you; see <A href="#offlineDetection">Best Practices for Online/Offline Detection</A> for a discussion on this topic.
      </P>
        
      <P>  
        You should also provide a settings dialog where the user can turn the offline feature off and create a new desktop shortcut icon if you are using the Gears <A href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</A>. Here is a screenshot of Google Docs offline settings pane:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline8.png">
      </P> 
      
      <P>
        As always, its good to provide short help text on what Gears is to the user so they can learn more about how your application is using their local machine in Gears. Clicking the Learn More link in the above screenshot leads to the following help text for Google Docs:
      </P>
      
      <P>
        <IMG src="./Gears FAQ - Gears API - Google Code_files/google_docs_offline9.png">
      </P>  
      
      <P>
        As a final note, make the offline experience match the online as much as possible, and use a consistent UI convention for disabling functionality.  With  Google Docs, we don't have an "offline editor" we have an offline mode.  When offline, certain features necessarily won't work.  But rather than hiding them or replacing them with a distinct UI, we simply gray them out.  That provides another clue to the user that they are in offline mode while retaining the familiarity of the application.
      </P>
    </DD>
    
    <DT id="maintainWorkers">
      Best Practices for Maintainable Workers
    </DT>
    
    <DD>
      <P>
        As your Gears-based projects get more sophisticated keeping your <A href="http://code.google.com/apis/gears/api_workerpool.html">Worker</A> code organized and maintainable can get tricky. Here are several tips and best practices for keeping things organized.
      </P>
      
      <P>
        First, you can use the WorkerPool <CODE><A href="http://code.google.com/apis/gears/api_workerpool.html#createworkerfromurl">createWorkerFromUrl</A></CODE> method to partition all of your worker script into a single file, which you can then instantiate to run on the worker.
      </P>
      
      <P>
        If you'd like to keep your primary application code and workers in the same file, however, you can 'stringify' specific methods and send them into the worker. It is also good practice to encapsulate external code from the fact that workers are being used; application code should simply be able to call a JavaScript class with data to be worked on and a callback, without being exposed to the Worker-specific implementation.
      </P>
      
      <P>
        Here is an example snippet of code where we have a Worker that will index a set of documents on a Worker into a full-text table in the Gears relational database. We encapsulate external callers of this code from this fact by creating creating a JavaScript 'class' named <CODE>Indexer</CODE> that can be called with an array of documents to index and a callback function when finished. Here's pseudo-code for the Indexer:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// constructor</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">Indexer</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">docs</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> callback</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">docs </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> docs</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">callback </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> callback</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">run_</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"> </SPAN><SPAN class="com">// kick off worker</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="typ">Indexer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">prototype</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">run_</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the code to run on the worker &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerScript </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="str">'var supportFunction_ = '</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">supportFunction_</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'; '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'google.gears.workerPool.onmessage = '</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">indexWorker_</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the message handler that gets return results from the worker</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> worker </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.workerpool'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; worker</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">onmessage </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> pu</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">hitch</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">a</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> b</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> message</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">message</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">text </SPAN><SPAN class="pun">==</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'finished'</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"> </SPAN><SPAN class="com">// we are done</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">});</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// send the worker a message to run</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> childWorkerId </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> worker</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createWorker</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">workerScript</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; worker</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">sendMessage</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">docs</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> childWorkerId</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="typ">Indexer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">prototype</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">indexWorker_</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the code that would run on the index worker goes here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="typ">Indexer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">prototype</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">supportFunction_</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// some support function needed inside the worker goes here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// callers using the call are encapsulated:</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> idx </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">new</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">Index</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">myDocs</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> myCallback</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        A few things to notice about the code above. First, we use JavaScript class notation to encapsulate our methods together. Second, we 'stringify' some of the methods inside of the class to pass into the worker using the <CODE>String()</CODE> method in JavaScript:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// the code to run on the worker &nbsp;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerScript </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="str">'var supportFunction_ = '</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">supportFunction_</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'; '</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'google.gears.workerPool.onmessage = '</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">indexWorker_</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        Calling <CODE>String()</CODE> on a function will simply output a stringified version of that function. For example, calling <CODE>String(this.supportFunction_)</CODE> outputs the following:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pun">()</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// some support function needed inside the worker goes here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        Notice that no function name is output; this is why we have to capture the stringified version into a variable when passing it into the worker:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> workerScript </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> &nbsp;</SPAN><SPAN class="str">'var supportFunction_ = '</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="typ">String</SPAN><SPAN class="pun">(</SPAN><SPAN class="kwd">this</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">supportFunction_</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        The <CODE>google.gears.workerPool.onmessage</CODE> assignment gives the WorkerPool <CODE>onmessage</CODE> method that will execute when the worker is sent a message. In our example code above, we make sure that the <CODE>indexWorker_</CODE> function will get run. You could have as many helper functions as necessary for this Worker to call by using the <CODE>String()</CODE> trick above. The code above makes it easy to encapsulate your Worker code into easy to call classes to keep your application bundled into a single JavaScript file.
      </P>
    </DD>
    
    <DT id="choosingNames">
      Best Practices for Choosing Names for Databases and LocalServers
    </DT>
    
    <DD>
      <P>
        When you open or create a Gears <A href="http://code.google.com/apis/gears/api_database.html">Database</A> or <A href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</A>, you must give them a name:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// LocalServer</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> localServer </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.localserver'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> store </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> localServer</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createManagedStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'test-store'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Database</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'test-database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        We recommend that you don't just choose a static string such as the <CODE>test-store</CODE> name given above for several reasons:
      </P>
      
      <UL>
        <LI>If you have several Gears applications on the same domain and they use the same string, your Databases and LocalServers can possibly collide creating hard to track down bugs.</LI>
        <LI>Even if you only have one Gears-based application hosted at your domain, if several users share the same OS-level account their data can get confused. For example, imagine you open a Database with the name <CODE>my-database</CODE> and store Bobs settings in there. Alice shares this computer with Bob using the same OS account. When Alice uses your web application you will open <CODE>my-database</CODE> again and over-write Bob's data.</LI> 
      </UL>
      
      <P>
        To mitigate these problems, we recommend the following algorithm (code is provided below as well implementing this):
      </P>
      
      <OL>
        <LI>Generate your Database or LocalServer name by using <CODE>window.location.href</CODE></LI>
        <LI>Pre-pend the user's account name to the beginning of the string, followed by an underscore.</LI>
        <LI>Pre-pend your application's name to the beginning, such as 'docs_'.
        </LI><LI>Replace any characters that <A href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">are not allowed</A> in the names so far by an underscore. Currently the name must consist only of visible ASCII characters excluding the following (spaces are also not allowed): / \ : * ? " &lt; &gt; | ; ,</LI>
        <LI>If the string is longer than 64 characters, trim it to 64 characters (64 is the longest allowed name).</LI>
      </OL>
      
      <P>
        If you don't have a concept of a user for your application you can safely ignore pre-pending the username. An example Database or LocalServer name generated from this algorithm is <CODE>search_someuser_http___example_com_myapp</CODE>. 
      </P>

      <P>
        Here is code that implements this algorithm that you can use:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> getGearsName</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">appName</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> userName</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> url </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> window</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">location</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">href</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> url</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">replace</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">/#(.*)$/</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">''</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> </SPAN><SPAN class="com">// remove anchor</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> name </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> appName </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'_'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">userName </SPAN><SPAN class="pun">?</SPAN><SPAN class="pln"> userName </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'_'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">''</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">+</SPAN><SPAN class="pln"> url</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// turn the following characters into underscores:</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// / \ : * ? " &lt; &gt; | ; , </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Gears should be able to allow spaces in db names but doesn't, </SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// so transform those too</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> name</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">replace</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">/\/|\\|:|\*|\?|\"|\&lt;|\&gt;|\||\;|\,|\.|\-|\=|[ ]/</SPAN><SPAN class="pln">g</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'_'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// Gears has a 64 character limit</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> name</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">substring</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">0</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="lit">63</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">return</SPAN><SPAN class="pln"> name</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        Note that if your URLs are very long, and you have two Gears-based applications that are only differentiated near the end of the URL, that you might still get a name collision due to the length of a Gears name being restricted to 64 characters.
      </P>

      <P>
        A final best practice is to use the following JavaScript idiom when working with a LocalServer; it makes your code a bit cleaner:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> server </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.localserver'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> name </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> getGearsName</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'myApp'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'someUser'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> store </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> server</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">openManagedStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">name</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">||</SPAN><SPAN class="pln"> server</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">createManagedStore</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">name</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        Notice the <CODE>||</CODE>; rather than having to have a large <CODE>if</CODE> block, we first try to open a <A href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</A> with the given name. If it doesn't exist then this method returns <CODE>false</CODE> and we short-circuit to the second part of the expression, which is to create a ManagedResourceStore with the given name.
      </P>
    </DD>
    
    <DT id="storingData">
      Best Practices for Storing Data on Users' Machines
    </DT>
    
    <DD>
      <P> 
        If you are using the Gears <A href="http://code.google.com/apis/gears/api_database.html">Database</A> or the <A href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">LocalServer</A> and are storing sensitive data on the local machine, you should make sure not to store your data on a public, sharable machine, such as at an Internet cafe. To ensure this, your application should do the following:
      </P>
      
      <UL>
        <LI>If a user turns on Gears, such as for offline ability or caching data, don't turn it on just for the user account. Instead, turn it on for this user <EM>plus</EM> the machine they are on. The best way to do this is to generate a <A href="http://en.wikipedia.org/wiki/GUID">GUID</A>, store it into the machine's Gears database, and then send this to the server. On the server you can save this GUID plus the account handle as being Gears enabled. If the user later uses your web application on a different machine, it will not be Gears enabled on that machine even though they are signed into the same account.</LI>
        <LI>When the user enables the feature that uses Gears to store sensitive data, you should inform the user not to enable this on a shared, public machine. As an example, here is the dialog that <A href="http://www.myspace.com/">MySpace</A> shows when activating the search feature of MySpace Mail, which uses Gears:<BR> 
          <IMG src="./Gears FAQ - Gears API - Google Code_files/myspace_permission_dialog.png">
        </LI>
      </UL>
      
      <P>
        If your feature does not store sensitive data, such as the <A href="#startGearsSpeedUp">editor caching that </A><A href="http://www.wordpress.com/">WordPress</A> does for faster access, then you can safely ignore this Best Practice.
      </P>
    </DD>
    
    <DT id="desktopShortcuts">
      Best Practices for Desktop Shortcuts
    </DT>
    
    <DD>
      <P> 
        The <A href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</A> makes it easy for applications to drop a shortcut on to a user's desktop for quickly opening your web application. This is useful if you have an offline application and want to make it easy for the user to access it even when the network is not available.
      </P>
      
      <P>
        Creating the Desktop API involved balancing both the interests of end-users and developers. We don't want to create a situation where a web-site can bother a user over and over to create a shortcut icon even when they don't want to. For this reason, we do not provide a way to query whether a desktop shortcut has been created before. Instead, we recommend the following:
      </P>
      
      <P>
        When a user has indicated they would like to use your application offline by clicking on some user interface element (see <A href="#bestGearsPerms">Best Practices for Gears Permissioning</A> and <A href="#offlineUI">Best Practices for Offline User Interfaces</A>), your application should attempt to create a desktop icon by calling the Gears Desktop <CODE>createShortcut</CODE> method. This will cause the Gears permission prompt to appear. You should then store in the local Gears database that the user was given the option to create a desktop icon. Note that you aren't storing whether the user gave your website permission or not, since there is no way to know that. Instead, you are simply storing that the user has been prompted before.
      </P>
      
      <P>
        Once this has been done, you should not prompt the user again. Instead, in the Settings pane for your application or another suitable area you should provide a button that says "Create Desktop Shortcut". When pressed, you can call the <CODE>createShortcut</CODE> method again to prompt the user to create a desktop icon again in case they changed their mind or deleted the old one and want to create it again.
      </P>
    </DD> 
    
    <DT id="versionDBSchema">
      Best Practices for Versioning Database Schema
    </DT>

    <DD>
      <P>
        A common issue with Gears-based applications that will be deployed for a long period of time is evolving the client-side database schema. Here are some best practices and tips for doing this.
      </P>
      
      <P>
        First, it is good to create a metadata table that versions your schema and optionally has the full <CODE>CREATE TABLE</CODE> SQL code in it for later reference. When you need to evolve your schema, iterate the version number and send over JavaScript that has an <CODE>upgradeDatabase</CODE> method that takes the new version number of the SQL to work with.
      </P>
      
      <P>
        Inside this method, you should load the current version number and compare it against the new version number to know whether to upgrade or not. For example, if the schema on the client is version <CODE>2.5</CODE>, and the new version for the upgraded schema is <CODE>2.6</CODE>, then you know you need to upgrade this client. If they are the same then obviously you don't need to upgrade the schema.
      </P>
      
      <P>
        Once you know you need to upgrade the schema, you should have different blocks where you can upgrade different old version numbers to the latest version; also make sure you surround the entire upgrade process in a transaction. Pseudocode:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// in our example we pass in 2.6 as the migrationVersion</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">function</SPAN><SPAN class="pln"> upgradeDatabase</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">migrationVersion</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> db </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> google</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">gears</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">factory</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">create</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'beta.database'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">open</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'my-db'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">try</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// get the current version</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> rs </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'SELECT version FROM DATABASE_METADATA'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">var</SPAN><SPAN class="pln"> currentVersion </SPAN><SPAN class="pun">=</SPAN><SPAN class="pln"> rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">fieldByName</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'version'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// upgrade needed?</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">migrationVersion </SPAN><SPAN class="pun">===</SPAN><SPAN class="pln"> currentVersion</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">return</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// upgrade</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'BEGIN TRANSACTION'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// do different upgrades for older versions</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">switch</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">currentVersion</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">case</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'2.4'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// SQL to upgrade 2.4 to 2.5 goes here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">break</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">case</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'2.5'</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// SQL to upgrade 2.5 to 2.6 goes here</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">break</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// SQL to store newly updated version goes here; currentVersion</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// should now be one version ahead</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="com">// recursively call method to upgrade to next version</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upgradeDatabase</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">currentVersion</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"><BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'END TRANSACTION'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"> </SPAN><SPAN class="kwd">finally</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="kwd">if</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">rs</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rs</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">close</SPAN><SPAN class="pun">();</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </SPAN><SPAN class="pun">}</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        You can also create a corollary <CODE>downgradeDatabase</CODE> to downgrade the current database schema if necessary for a rollback. 
      </P>
      
      <P>
        An independent, non-Google open source library named <A href="http://m.ac.nz/gearshift/">Gearshift</A> is available to help with database migrations and schema versioning.
      </P>
    </DD>   

    <DT id="useMRS">
      Best Practices for LocalServer
    </DT>

    <DD>
      <P>
        In most cases, use the <A href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</A>. It is meant to be used for application resources such as CSS, HTML, JavaScript, and images. It is good because it enables you to push your updated application in one step to the clients.
      </P>
      <P>
        The <A href="http://code.google.com/apis/gears/api_localserver.html#ResourceStore">ResourceStore</A> is meant to be more of a specialized tool and should be used accordingly. For instance, if your application has user-generated content or user-specific data then it would be difficult to control it with a ManagedResourceStore. Using a ResourceStore to handle this dynamic content is ideal.
      </P>
    </DD>

    <DT id="syncing">
      Best Practices for Syncing
    </DT>

    <DD>
      <P>
        As soon as you take an application offline (or use the Gears <A href="http://code.google.com/apis/gears/api_database.html">Database</A> to cache data for faster performance), you will run into the issue of syncing. Here are some tips and Best Practices for this situation.
      </P>

      <P>
        First, the more you can avoid syncing the better. See <A href="#bestPracticeStartGears">Best Practices for Starting With Gears</A> to make sure you want to start with a web application that requires syncing. Gears can be used for many other uses that don't need syncing.
      </P>
      
      <P>
        When it comes to syncing there is actually a spectrum of choices, ranging from easiest to hardest depending on the nature of your application. The following are some syncing scenarios from simplest to most complex; the further in the list you go the more challenging syncing becomes:
      </P>
      
      <OL>
        <LI>Read only throw away cache. This is a read-only cache stored in the local database that you throw away every time you sync. An example of this would be downloading a user's daily todo list, where every time you sync you throw away the local database's results and re-download all the new data.</LI>
        <LI>Read only cache that you incrementally update with new data. This is a read only cache that you use offline or for performance; on syncs you download new data to append to this cache or partially replace the data that is present for greater efficiency. An example of this would be <A href="http://gearsblog.blogspot.com/2008/05/myspace-message-center-is-now-searching.html">MySpace Mail's usage of Gears</A>. At regular intervals MySpace Mail downloads a user's newest messages into the local database, keeping the old ones present to search over.</LI>
        <LI>Read/write cache for single user. Data is downloaded and stored locally that originates from a single user. While offline a user can write to and update this data. When the user goes back online the data is synced. Since the data originates from a single-user the potential for conflict is less. However, keep in mind that a single-user can still be using Gears on multiple laptops, with offline data that might collide when they go back online. An example of this kind of data would be storing and writing emails while offline.</LI>
        <LI>Read/write cache for multiple users without merging. In this scenario, users pull down data that is shared amongst multiple users. While offline they edit and change the data. When online the data is synced. Since the data is multi-user, the possibility exists that other users have changed the same data. In this scenario the syncing doesn't attempt to do automatic tricky conflict resolution and merging. For example, if user A edits the same document as user B, we would not try to merge the two documents together but rather have the last person who synced change the document. An example of this scenario is a collaborative, multi-user word processor such as <A href="http://zoho.com/">Zoho</A>. Zoho, for example, does not attempt automatic merging of offline documents between multiple users.</LI>
        <LI>Read/write cache for multiple users with automatic merging. This is the hardest. Data that has conflicts or were edited by multiple users are either automatically merged (which can be challenging for HTML documents, for example), or a conflict resolution UI is shown to the user where automatic merging can not be done.</LI>
      </OL>
      
      <P>
        When determining your syncing strategy, the more you can choose syncing scenarios that are near the top of the list above the easier things will be.
      </P>
      
      <P>
        Handling these different scenarios requires different tools. Lets take a look at each.
      </P>
      
      <P id="syncReadThrowAway">
        <EM>Read only throw away cache</EM>
      </P>
      
      <P>
        As stated, this scenario is the simplest. At each sync cycle simply delete your local database and re-download all the data necessary to work offline.
      </P>
      
      <P id="syncReadUpdate">
        <EM>Read only cache that you incrementally update with new data</EM>
      </P>
      
      <P>    
        First, in the local data that you download you should have a key of some kind that the server knows how to work with. For example, if you were downloading messages to store locally the server would want to include a <CODE>message_id</CODE> column that maps to a server-known ID to uniquely identify any messages that are downloaded.
      </P>
      
      <P>
        Your sync sessions can be separated into three phases:
      </P>
      
      <OL>
        <LI>Download new data. This is where you download data that was not present before, simply appending rows to your tables.</LI>
        <LI>Delete data. This is where you delete data that is no longer valid, possibly cleaning up references to these deleted rows from data that is still valid.</LI>
        <LI>Update data. This is where the server foreign key comes in handy. The server can either send over JavaScript or JSON to update tables using the known keys or send over SQL to execute.
      </LI></OL>
      
      <P>
        If your application simply appends new data to an existing table without updating or invalidating existing data than you can ignore steps two and three.
      </P>
      
      <P>
        Updating existing data is the trickest. The server can either send over JavaScript for the client to simply execute which will do the syncing, or send over SQL to execute on the client-side.
      </P>
      
      <P>
        In the scenario where the server sends over JavaScript to run during syncing, imagine that we have a function named <CODE>updateContact</CODE> that can be called over and over in some JavaScript sent over from the server. This function takes the foreign key we identified earlier, such as a <CODE>contact_id</CODE> that is also present on the server, and then takes a list of column names to update along with the new values. During syncing imagine that the server sends the following, which you execute on the client-side by calling JavaScript's <CODE>eval</CODE> function:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; updateContact</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">55</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln">first_name</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'Brad'</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> favorite_color</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'blue'</SPAN><SPAN class="pun">});</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; updateContact</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">100</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> </SPAN><SPAN class="pun">{</SPAN><SPAN class="pln">last_name</SPAN><SPAN class="pun">:</SPAN><SPAN class="pln"> </SPAN><SPAN class="str">'Jones'</SPAN><SPAN class="pun">});</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P>
        A server could also send over SQL to execute against the client's local database:
      </P>
      
      <PRE class="prettyprint"><SPAN class="pln">&nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'UPDATE CONTACT SET first_name = '</SPAN><SPAN class="typ">Brad</SPAN><SPAN class="str">', favorite_color = '</SPAN><SPAN class="pln">blue</SPAN><SPAN class="str">' WHERE contact_id = 55'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; &nbsp; db</SPAN><SPAN class="pun">.</SPAN><SPAN class="pln">execute</SPAN><SPAN class="pun">(</SPAN><SPAN class="str">'UPDATE CONTACT SET last_name = '</SPAN><SPAN class="typ">Jones</SPAN><SPAN class="str">' WHERE contact_id = 100'</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"><BR>&nbsp; &nbsp; &nbsp; </SPAN></PRE>
      
      <P id="syncReadWrite">
        <EM>Read/Write Scenarios</EM>
      </P>
      
      <P>
        As soon as you move into the write scenario it is best to move towards a transactional model where you keep a log of actions the user has done while offline, then replay this log when the network reappears.
      </P>
      
      <P>
        The Dojo Offline tutorial has a good treatment on this topic <A href="http://docs.google.com/View?docid=dhkhksk4_8gdp9gr#sync">here</A>. Omar Kilani from <A href="http://www.rememberthemilk.com/">Remember the Milk</A> describes their syncing strategy in a tutorial <A href="http://code.google.com/support/bin/answer.py?answer=73848&topic=11982">here</A>. An excerpt:
      </P>
      
      <BLOCKQUOTE>
        <P>
          Remember The Milk implements synchronization using a sorted action log that specifies which actions were taken offline and properties affected by these actions, and a local addition table that holds the locally assigned unique IDs (LUIDs) of any objects created by the client.
        </P>
        
        <P>
          When synchronization is initiated, the client sends the action log and any local object additions to the server, which automatically handles conflicts. (Conflict resolution was already implemented in RTM to handle cases where multiple users may be working with the same task list.)
        </P>
        
        <P>
          If there were client-side additions, the unique IDs assigned to those objects may differ from the IDs chosen by the server during the synchronization process. To account for this, the server sends the client a local-to-global ID map, which is used to remap the IDs of client-created in-memory objects and database entries to those on the server.
        </P>
        
        <P>
          Once synchronization is finished, the client then requests the latest versions of its data set from the server to retrieve any server-side changes that occurred while the client was offline.
        </P>
        
        <P>
          RTM attempts to synchronize with the server on every application launch (if connectivity is detected).
        </P>
      </BLOCKQUOTE>
      
      <P id="syncSyncConstantly">
        <EM>The Always Syncing Model</EM>
      </P>
      
      <P>
        In some applications the best approach is to always operate with local data and sync periodically, independently of whether you are on- or offline.  A great example of this is 
      <A href="http://gdata-javascript-client.googlecode.com/svn/trunk/samples/blogger/bloggears/bloggears.html">Blog.Gears</A>. More discussion on this model can be found <A href="http://code.google.com/apis/gears/architecture.html">here</A>.
      </P>
      
      <P id="syncWhenHowMuch">
        <EM>Deciding when and how much to sync</EM>
      </P>
      
      <P>
        Two more decisions remain to be made around syncing. First, you need to decide <EM>when</EM> to sync, and second, you must decide <EM>how much</EM> to sync and download.
      </P>
      
      <P>
        Syncing can kick off:
      </P>
      
      <UL>
        <LI>Manually by the user with a sync button. This is the easiest to implement but puts the burden on the user. Its a good first choice to get running code quickly.</LI>
        <LI>Automatically in the background at regular intervals and when the network reappears if offline.</LI>
      </UL>
      
      <P>
        You must also decide how much data to download. If the data set is small enough you can simply download all the data at once and then trickle in updates over time. If dealing with a large data set you will have to make intelligent choices about what to download. For example, if downloading a user's emails with an extremely large inbox you could choose to just download several thousand ranked by newest to oldest. If you want to download all of the data even with a large data set, you can choose to download an initial subset and then trickle down pieces of the remaining, older data at regular intervals in the background over time.
      </P>
      
      <P>
        Finally, a number of open source frameworks exist which can help with syncing while using Gears:
      </P>

      <UL>
        <LI><A href="http://dojotoolkit.org/offline">Dojo Offline Toolkit</A></LI>
        <LI><A href="http://code.google.com/p/trimpath/wiki/TrimJunction">Trimpath Junction</A></LI>
      </UL>
    </DD>
    
    <DT id="webAppAsDesktop">
      Best Practices for Giving Web Applications Similar Features to Desktop Applications
    </DT>

    <DD>
      <UL>
        <LI>
          Use the 
          <A href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</A>
          to have an icon to your application. See <A href="#desktopShortcuts">Best Practices for Desktop Shortcuts</A> for details.
        </LI>
        <LI>
          Refer to the <A href="#syncing">syncing best practices</A> to create a
          seamless data syncing experience
        </LI>
        <LI>Operate on local data so the application is snappy</LI>
        <LI>
          Use <A href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</A> to provide an auto-update mechanism for your
          application
        </LI>
        <LI>Benefits of a web app as a desktop app:</LI>
        <UL>
          <LI>
            One codebase vs. a desktop application's various client 
            (OS X, Linux, Windows) codebases
          </LI>
          <LI>
            Easy auto-update mechanism 
            (updating JavaScript, HTML, CSS, manifest version number) vs. desktop
            application's complicated software update process
          </LI>
        </UL>
      </UL>  
    </DD>

  
 <DIV id="gc-collapsible" style="height: 25773px; " class=""></DIV></DIV><!-- end gc-pagecontent -->
 </DIV><!-- end gooey wrapper -->

 </DIV> <!-- end codesite content -->

</DIV><!-- end gc-containter -->

<SCRIPT type="text/javascript">CODESITE_CSITimer['load'].tick('ats');</SCRIPT>
<SCRIPT src="./Gears FAQ - Gears API - Google Code_files/codesite_tail.pack.04102009.js" type="text/javascript"></SCRIPT>








 


<DIV class="menuDiv instance0" id="menuDiv-projects-dropdown" style="position: absolute; display: none; top: 22px; left: 1189px; "><B class="categoryTitle projects" style="display: block; ">Projects</B><DIV class="menuCategory projects first"><A class="menuItem" style="display: block; " href="http://code.google.com/p/d-zadania/">d-zadania</A><A class="menuItem" style="display: block; " href="http://code.google.com/p/osullivan/">osullivan</A><A class="menuItem" style="display: block; " href="http://code.google.com/p/qfel13-webdb/">qfel13-webdb</A><A class="menuItem" style="display: block; " href="http://code.google.com/p/simadmin/">simadmin</A></DIV><B class="categoryTitle starred_projects" style="display: block; ">Starred projects</B><DIV class="menuCategory starred_projects"><A class="menuItem" style="display: block; " href="http://code.google.com/p/gears/">gears</A><A class="menuItem" style="display: block; " href="http://code.google.com/p/gwt-google-apis/">gwt-google-apis</A></DIV><DIV class="menuCategory controls"><HR class="menuSeparator"><A class="menuItem" style="display: block; " href="http://code.google.com/more/">Find developer products...</A><A class="menuItem" style="display: block; " href="http://code.google.com/hosting/">Find open source projects...</A></DIV></DIV><DIV class="menuDiv instance1" id="menuDiv-lang-dropdown" style="position: absolute; display: none; top: 22px; left: 1284px; width: 175px; "><DIV class="menuCategory default first"><A class="menuItem" style="display: block; " href="http://code.google.com/intl/en/apis/gears/gears_faq.html">English</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/es/apis/gears/gears_faq.html">Español</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/ja/apis/gears/gears_faq.html">日本語</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/ko/apis/gears/gears_faq.html">한국어</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/pt-BR/apis/gears/gears_faq.html">Português (Brasil)</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/ru/apis/gears/gears_faq.html">Pусский</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/zh-CN/apis/gears/gears_faq.html">中文 (简体)</A><A class="menuItem" style="display: block; " href="http://code.google.com/intl/zh-TW/apis/gears/gears_faq.html">中文 (繁體)</A></DIV></DIV><DIV id="gc-collapsible-arrow" class="" style="left: 182px; top: 1113px; display: none; "></DIV><DIV id="cs-searchresults" style="left: 181px; top: 76px; width: 345px; "><DIV id="cs-recommended">Suggestions</DIV><DIV id="searchResult1"></DIV><DIV id="searchResult2"></DIV><DIV id="searchResult3"></DIV><DIV id="searchResult4"></DIV><DIV id="searchResult5"></DIV><DIV id="searchResult6"></DIV><DIV id="searchResult7"></DIV></DIV></BODY></HTML>